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/01/01 19:11:56 UTC

[01/32] syncope git commit: Merge branch '1_2_X' of https://git-wip-us.apache.org/repos/asf/syncope into 1_2_X

Repository: syncope
Updated Branches:
  refs/heads/2_0_X c73a73b09 -> 556d51862


Merge branch '1_2_X' of https://git-wip-us.apache.org/repos/asf/syncope into 1_2_X


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

Branch: refs/heads/2_0_X
Commit: 3629cc120e5580a8783ce95da6fad2e1fb8c4b33
Parents: 20bfa94 386b86a
Author: Marco Di Sabatino Di Diodoro <md...@apache.org>
Authored: Mon Dec 22 10:11:19 2014 +0100
Committer: Marco Di Sabatino Di Diodoro <md...@apache.org>
Committed: Mon Dec 22 10:11:19 2014 +0100

----------------------------------------------------------------------
 pom.xml | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------



[25/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractPlainSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractPlainSchema.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractPlainSchema.java
new file mode 100644
index 0000000..075252a
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractPlainSchema.java
@@ -0,0 +1,271 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import java.lang.reflect.Constructor;
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Id;
+import javax.persistence.Lob;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.Transient;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.CipherAlgorithm;
+import org.apache.syncope.persistence.api.attrvalue.validation.Validator;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.apache.syncope.persistence.jpa.attrvalue.validation.BasicValidator;
+import org.apache.syncope.persistence.jpa.validation.entity.PlainSchemaCheck;
+import org.apache.syncope.persistence.jpa.validation.entity.SchemaNameCheck;
+
+@MappedSuperclass
+@PlainSchemaCheck
+@SchemaNameCheck
+public abstract class AbstractPlainSchema extends AbstractEntity<String> implements PlainSchema {
+
+    private static final long serialVersionUID = -8621028596062054739L;
+
+    @Id
+    private String name;
+
+    @Column(nullable = false)
+    @Enumerated(EnumType.STRING)
+    private AttrSchemaType type;
+
+    @Column(nullable = false)
+    private String mandatoryCondition;
+
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer multivalue;
+
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer uniqueConstraint;
+
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer readonly;
+
+    @Column(nullable = true)
+    private String conversionPattern;
+
+    @Column(nullable = true)
+    private String validatorClass;
+
+    @Column(nullable = true)
+    @Lob
+    private String enumerationValues;
+
+    @Column(nullable = true)
+    @Lob
+    private String enumerationKeys;
+
+    @Column(nullable = true)
+    private String secretKey;
+
+    @Column(nullable = true)
+    @Enumerated(EnumType.STRING)
+    private CipherAlgorithm cipherAlgorithm;
+
+    @Column(nullable = true)
+    private String mimeType;
+
+    @Transient
+    private Validator validator;
+
+    public AbstractPlainSchema() {
+        super();
+
+        type = AttrSchemaType.String;
+        mandatoryCondition = Boolean.FALSE.toString();
+        multivalue = getBooleanAsInteger(false);
+        uniqueConstraint = getBooleanAsInteger(false);
+        readonly = getBooleanAsInteger(false);
+    }
+
+    @Override
+    public String getKey() {
+        return name;
+    }
+
+    @Override
+    public void setKey(final String name) {
+        this.name = name;
+    }
+
+    @Override
+    public AttrSchemaType getType() {
+        return type;
+    }
+
+    @Override
+    public void setType(final AttrSchemaType type) {
+        this.type = type;
+    }
+
+    @Override
+    public String getMandatoryCondition() {
+        return mandatoryCondition;
+    }
+
+    @Override
+    public void setMandatoryCondition(final String condition) {
+        this.mandatoryCondition = condition;
+    }
+
+    @Override
+    public boolean isMultivalue() {
+        return isBooleanAsInteger(multivalue);
+    }
+
+    @Override
+    public void setMultivalue(boolean multivalue) {
+        this.multivalue = getBooleanAsInteger(multivalue);
+    }
+
+    @Override
+    public boolean isUniqueConstraint() {
+        return isBooleanAsInteger(uniqueConstraint);
+    }
+
+    @Override
+    public void setUniqueConstraint(final boolean uniquevalue) {
+        this.uniqueConstraint = getBooleanAsInteger(uniquevalue);
+    }
+
+    @Override
+    public boolean isReadonly() {
+        return isBooleanAsInteger(readonly);
+    }
+
+    @Override
+    public void setReadonly(final boolean readonly) {
+        this.readonly = getBooleanAsInteger(readonly);
+    }
+
+    @Override
+    public Validator getValidator() {
+        if (validator != null) {
+            return validator;
+        }
+
+        if (getValidatorClass() != null && getValidatorClass().length() > 0) {
+            try {
+                Constructor<?> validatorConstructor = Class.forName(getValidatorClass()).
+                        getConstructor(new Class<?>[] { PlainSchema.class });
+                validator = (Validator) validatorConstructor.newInstance(this);
+            } catch (Exception e) {
+                LOG.error("Could not instantiate validator of type {}, reverting to {}",
+                        getValidatorClass(), BasicValidator.class.getSimpleName(), e);
+            }
+        }
+
+        if (validator == null) {
+            validator = new BasicValidator(this);
+        }
+
+        return validator;
+    }
+
+    @Override
+    public String getValidatorClass() {
+        return validatorClass;
+    }
+
+    @Override
+    public void setValidatorClass(final String validatorClass) {
+        this.validatorClass = validatorClass;
+    }
+
+    @Override
+    public String getEnumerationValues() {
+        return enumerationValues;
+    }
+
+    @Override
+    public void setEnumerationValues(final String enumerationValues) {
+        this.enumerationValues = enumerationValues;
+    }
+
+    @Override
+    public String getEnumerationKeys() {
+        return enumerationKeys;
+    }
+
+    @Override
+    public void setEnumerationKeys(String enumerationKeys) {
+        this.enumerationKeys = enumerationKeys;
+    }
+
+    @Override
+    public String getConversionPattern() {
+        if (!getType().isConversionPatternNeeded()) {
+            LOG.debug("Conversion pattern is not needed: {}'s type is {}", this, getType());
+        }
+
+        return conversionPattern;
+    }
+
+    @Override
+    public void setConversionPattern(final String conversionPattern) {
+        if (!getType().isConversionPatternNeeded()) {
+            LOG.warn("Conversion pattern will be ignored: this attribute type is {}", getType());
+        }
+
+        this.conversionPattern = conversionPattern;
+    }
+
+    @Override
+    public String getSecretKey() {
+        return secretKey;
+    }
+
+    @Override
+    public void setSecretKey(final String secretKey) {
+        this.secretKey = secretKey;
+    }
+
+    @Override
+    public CipherAlgorithm getCipherAlgorithm() {
+        return cipherAlgorithm;
+    }
+
+    @Override
+    public void setCipherAlgorithm(final CipherAlgorithm cipherAlgorithm) {
+        this.cipherAlgorithm = cipherAlgorithm;
+    }
+
+    @Override
+    public String getMimeType() {
+        return mimeType;
+    }
+
+    @Override
+    public void setMimeType(final String mimeType) {
+        this.mimeType = mimeType;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractSubject.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractSubject.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractSubject.java
new file mode 100644
index 0000000..3628697
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractSubject.java
@@ -0,0 +1,64 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.syncope.persistence.api.entity.DerAttr;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.Subject;
+import org.apache.syncope.persistence.api.entity.VirAttr;
+
+public abstract class AbstractSubject<P extends PlainAttr, D extends DerAttr, V extends VirAttr>
+        extends AbstractAttributable<P, D, V> implements Subject<P, D, V> {
+
+    private static final long serialVersionUID = -6876467491398928855L;
+
+    protected abstract Set<? extends ExternalResource> internalGetResources();
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public boolean addResource(final ExternalResource resource) {
+        return ((Set<ExternalResource>) internalGetResources()).add(resource);
+    }
+
+    @Override
+    public boolean removeResource(final ExternalResource resource) {
+        return internalGetResources().remove(resource);
+    }
+
+    @Override
+    public Set<? extends ExternalResource> getResources() {
+        return internalGetResources();
+    }
+
+    @Override
+    public Set<String> getResourceNames() {
+        Set<? extends ExternalResource> ownResources = getResources();
+
+        Set<String> result = new HashSet<>(ownResources.size());
+        for (ExternalResource resource : ownResources) {
+            result.add(resource.getKey());
+        }
+
+        return result;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractVirAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractVirAttr.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractVirAttr.java
new file mode 100644
index 0000000..3805489
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractVirAttr.java
@@ -0,0 +1,62 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.Transient;
+import org.apache.syncope.persistence.api.entity.VirAttr;
+
+@MappedSuperclass
+public abstract class AbstractVirAttr extends AbstractEntity<Long> implements VirAttr {
+
+    private static final long serialVersionUID = 5023204776925954907L;
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.AUTO)
+    protected Long id;
+
+    @Transient
+    protected List<String> values = new ArrayList<>();
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public List<String> getValues() {
+        return values;
+    }
+
+    @Override
+    public boolean addValue(final String value) {
+        return !values.contains(value) && values.add(value);
+    }
+
+    @Override
+    public boolean removeValue(final String value) {
+        return values.remove(value);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractVirSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractVirSchema.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractVirSchema.java
new file mode 100644
index 0000000..311350e
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractVirSchema.java
@@ -0,0 +1,89 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import javax.persistence.Basic;
+import javax.persistence.Id;
+import javax.persistence.MappedSuperclass;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.persistence.api.entity.VirSchema;
+import org.apache.syncope.persistence.jpa.validation.entity.SchemaNameCheck;
+
+@MappedSuperclass
+@SchemaNameCheck
+public abstract class AbstractVirSchema extends AbstractEntity<String> implements VirSchema {
+
+    private static final long serialVersionUID = 3274006935328590141L;
+
+    @Id
+    private String name;
+
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer readonly;
+
+    public AbstractVirSchema() {
+        super();
+
+        readonly = getBooleanAsInteger(false);
+    }
+
+    @Override
+    public String getKey() {
+        return name;
+    }
+
+    @Override
+    public void setKey(final String key) {
+        this.name = key;
+    }
+
+    @Override
+    public AttrSchemaType getType() {
+        return AttrSchemaType.String;
+    }
+
+    @Override
+    public String getMandatoryCondition() {
+        return Boolean.FALSE.toString().toLowerCase();
+    }
+
+    @Override
+    public boolean isMultivalue() {
+        return Boolean.TRUE;
+    }
+
+    @Override
+    public boolean isUniqueConstraint() {
+        return Boolean.FALSE;
+    }
+
+    @Override
+    public boolean isReadonly() {
+        return isBooleanAsInteger(readonly);
+    }
+
+    @Override
+    public void setReadonly(final boolean readonly) {
+        this.readonly = getBooleanAsInteger(readonly);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AnnotatedEntityListener.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AnnotatedEntityListener.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AnnotatedEntityListener.java
new file mode 100644
index 0000000..e6ce64f
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AnnotatedEntityListener.java
@@ -0,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.persistence.jpa.entity;
+
+import java.util.Date;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import org.apache.syncope.persistence.api.entity.AnnotatedEntity;
+import org.apache.syncope.server.security.AuthContextUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AnnotatedEntityListener {
+
+    /**
+     * Logger.
+     */
+    private static final Logger LOG = LoggerFactory.getLogger(AnnotatedEntityListener.class);
+
+    @PrePersist
+    @PreUpdate
+    public void setSysInfo(final AnnotatedEntity entity) {
+        final String username = AuthContextUtil.getAuthenticatedUsername();
+        LOG.debug("Set system properties for '{}'", entity);
+
+        final Date now = new Date();
+
+        if (entity.getCreationDate() == null) {
+            LOG.debug("Set creation date '{}' and creator '{}' for '{}'", now, username, entity);
+            entity.setCreationDate(now);
+            entity.setCreator(username);
+        }
+
+        LOG.debug("Set last change date '{}' and modifier '{}' for '{}'", now, username, entity);
+        entity.setLastModifier(username);
+        entity.setLastChangeDate(now);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAAccountPolicy.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAAccountPolicy.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAAccountPolicy.java
new file mode 100644
index 0000000..229dd43
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAAccountPolicy.java
@@ -0,0 +1,90 @@
+/*
+ * 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.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 javax.validation.Valid;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.syncope.persistence.api.entity.AccountPolicy;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+
+@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 = "account_policy_id"),
+            inverseJoinColumns =
+            @JoinColumn(name = "resource_name"))
+    @Valid
+    private Set<JPAExternalResource> resources;
+
+    public JPAAccountPolicy() {
+        this(false);
+        this.resources = new HashSet<>();
+    }
+
+    public JPAAccountPolicy(final boolean global) {
+        super();
+
+        this.type = global
+                ? PolicyType.GLOBAL_ACCOUNT
+                : PolicyType.ACCOUNT;
+    }
+
+    @Override
+    public boolean addResource(final ExternalResource resource) {
+        checkType(resource, JPAExternalResource.class);
+        return resources.add((JPAExternalResource) resource);
+    }
+
+    @Override
+    public boolean removeResource(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() {
+        Set<String> result = new HashSet<>(resources.size());
+        for (ExternalResource resource : resources) {
+            result.add(resource.getKey());
+        }
+
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAAttributableUtil.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAAttributableUtil.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAAttributableUtil.java
new file mode 100644
index 0000000..2705285
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAAttributableUtil.java
@@ -0,0 +1,882 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.persistence.api.entity.AttrTemplate;
+import org.apache.syncope.persistence.api.entity.Attributable;
+import org.apache.syncope.persistence.api.entity.AttributableUtil;
+import org.apache.syncope.persistence.api.entity.DerAttr;
+import org.apache.syncope.persistence.api.entity.DerSchema;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.MappingItem;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.apache.syncope.persistence.api.entity.VirAttr;
+import org.apache.syncope.persistence.api.entity.VirSchema;
+import org.apache.syncope.persistence.api.entity.conf.Conf;
+import org.apache.syncope.persistence.api.entity.membership.Membership;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.entity.conf.JPACPlainAttr;
+import org.apache.syncope.persistence.jpa.entity.conf.JPACPlainAttrUniqueValue;
+import org.apache.syncope.persistence.jpa.entity.conf.JPACPlainAttrValue;
+import org.apache.syncope.persistence.jpa.entity.conf.JPACPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.conf.JPAConf;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMDerAttr;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMDerAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMDerSchema;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMPlainAttr;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMPlainAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMPlainAttrUniqueValue;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMPlainAttrValue;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMVirAttr;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMVirAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMVirSchema;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMembership;
+import org.apache.syncope.persistence.jpa.entity.role.JPARDerAttr;
+import org.apache.syncope.persistence.jpa.entity.role.JPARDerAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.role.JPARDerSchema;
+import org.apache.syncope.persistence.jpa.entity.role.JPARMappingItem;
+import org.apache.syncope.persistence.jpa.entity.role.JPARPlainAttr;
+import org.apache.syncope.persistence.jpa.entity.role.JPARPlainAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.role.JPARPlainAttrUniqueValue;
+import org.apache.syncope.persistence.jpa.entity.role.JPARPlainAttrValue;
+import org.apache.syncope.persistence.jpa.entity.role.JPARPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.role.JPARVirAttr;
+import org.apache.syncope.persistence.jpa.entity.role.JPARVirAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.role.JPARVirSchema;
+import org.apache.syncope.persistence.jpa.entity.role.JPARole;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUDerAttr;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUDerSchema;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUMappingItem;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUPlainAttr;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUPlainAttrUniqueValue;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUPlainAttrValue;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUVirAttr;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUVirSchema;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUser;
+import org.apache.syncope.server.spring.BeanUtils;
+import org.identityconnectors.framework.common.objects.ObjectClass;
+import org.identityconnectors.framework.common.objects.Uid;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings({ "unchecked", "rawtypes" })
+public class JPAAttributableUtil implements AttributableUtil {
+
+    /**
+     * Logger.
+     */
+    private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(AttributableUtil.class);
+
+    public static AttributableUtil getInstance(final AttributableType type) {
+        return new JPAAttributableUtil(type);
+    }
+
+    public static AttributableUtil valueOf(final String name) {
+        return new JPAAttributableUtil(AttributableType.valueOf(name));
+    }
+
+    public static AttributableUtil getInstance(final ObjectClass objectClass) {
+        AttributableType type = null;
+        if (ObjectClass.ACCOUNT.equals(objectClass)) {
+            type = AttributableType.USER;
+        }
+        if (ObjectClass.GROUP.equals(objectClass)) {
+            type = AttributableType.ROLE;
+        }
+
+        if (type == null) {
+            throw new IllegalArgumentException("ObjectClass not supported: " + objectClass);
+        }
+
+        return new JPAAttributableUtil(type);
+    }
+
+    public static AttributableUtil getInstance(final Attributable attributable) {
+        AttributableType type = null;
+        if (attributable instanceof User) {
+            type = AttributableType.USER;
+        }
+        if (attributable instanceof Role) {
+            type = AttributableType.ROLE;
+        }
+        if (attributable instanceof Membership) {
+            type = AttributableType.MEMBERSHIP;
+        }
+        if (attributable instanceof Conf) {
+            type = AttributableType.CONFIGURATION;
+        }
+
+        if (type == null) {
+            throw new IllegalArgumentException("Attributable type not supported: " + attributable.getClass().getName());
+        }
+
+        return new JPAAttributableUtil(type);
+    }
+
+    private final AttributableType type;
+
+    private JPAAttributableUtil(final AttributableType type) {
+        this.type = type;
+    }
+
+    @Override
+    public AttributableType getType() {
+        return type;
+    }
+
+    @Override
+    public <T extends Attributable<?, ?, ?>> Class<T> attributableClass() {
+        Class result;
+
+        switch (type) {
+            case ROLE:
+                result = JPARole.class;
+                break;
+
+            case MEMBERSHIP:
+                result = JPAMembership.class;
+                break;
+
+            case CONFIGURATION:
+                result = JPAConf.class;
+                break;
+
+            case USER:
+            default:
+                result = JPAUser.class;
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends PlainSchema> Class<T> plainSchemaClass() {
+        Class result;
+
+        switch (type) {
+            case ROLE:
+                result = JPARPlainSchema.class;
+                break;
+
+            case MEMBERSHIP:
+                result = JPAMPlainSchema.class;
+                break;
+
+            case CONFIGURATION:
+                result = JPACPlainSchema.class;
+                break;
+
+            case USER:
+            default:
+                result = JPAUPlainSchema.class;
+                break;
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends PlainSchema> T newPlainSchema() {
+        T result = null;
+
+        switch (type) {
+            case USER:
+                result = (T) new JPAUPlainSchema();
+                break;
+
+            case ROLE:
+                result = (T) new JPARPlainSchema();
+                break;
+
+            case MEMBERSHIP:
+                result = (T) new JPAMPlainSchema();
+                break;
+
+            case CONFIGURATION:
+                result = (T) new JPACPlainSchema();
+            default:
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends PlainAttr> Class<T> plainAttrClass() {
+        Class result = null;
+
+        switch (type) {
+            case ROLE:
+                result = JPARPlainAttr.class;
+                break;
+
+            case MEMBERSHIP:
+                result = JPAMPlainAttr.class;
+                break;
+
+            case CONFIGURATION:
+                result = JPACPlainAttr.class;
+                break;
+
+            case USER:
+            default:
+                result = JPAUPlainAttr.class;
+                break;
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends PlainAttr> T newPlainAttr() {
+        T result = null;
+
+        switch (type) {
+            case USER:
+                result = (T) new JPAUPlainAttr();
+                break;
+
+            case ROLE:
+                result = (T) new JPARPlainAttr();
+                break;
+
+            case MEMBERSHIP:
+                result = (T) new JPAMPlainAttr();
+                break;
+
+            case CONFIGURATION:
+                result = (T) new JPACPlainAttr();
+
+            default:
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends PlainAttrValue> Class<T> plainAttrValueClass() {
+        Class result;
+
+        switch (type) {
+            case ROLE:
+                result = JPARPlainAttrValue.class;
+                break;
+
+            case MEMBERSHIP:
+                result = JPAMPlainAttrValue.class;
+                break;
+
+            case CONFIGURATION:
+                result = JPACPlainAttrValue.class;
+                break;
+
+            case USER:
+            default:
+                result = JPAUPlainAttrValue.class;
+                break;
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends PlainAttrValue> T newPlainAttrValue() {
+        T result = null;
+
+        switch (type) {
+            case USER:
+                result = (T) new JPAUPlainAttrValue();
+                break;
+
+            case ROLE:
+                result = (T) new JPARPlainAttrValue();
+                break;
+
+            case MEMBERSHIP:
+                result = (T) new JPAMPlainAttrValue();
+                break;
+
+            case CONFIGURATION:
+                result = (T) new JPACPlainAttrValue();
+                break;
+
+            default:
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends PlainAttrValue> Class<T> plainAttrUniqueValueClass() {
+        Class result;
+
+        switch (type) {
+            case ROLE:
+                result = JPARPlainAttrUniqueValue.class;
+                break;
+
+            case MEMBERSHIP:
+                result = JPAMPlainAttrUniqueValue.class;
+                break;
+
+            case CONFIGURATION:
+                result = JPACPlainAttrUniqueValue.class;
+                break;
+
+            case USER:
+            default:
+                result = JPAUPlainAttrUniqueValue.class;
+                break;
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends PlainAttrValue> T newPlainAttrUniqueValue() {
+        T result = null;
+
+        switch (type) {
+            case USER:
+                result = (T) new JPAUPlainAttrUniqueValue();
+                break;
+
+            case ROLE:
+                result = (T) new JPARPlainAttrUniqueValue();
+                break;
+
+            case MEMBERSHIP:
+                result = (T) new JPAMPlainAttrUniqueValue();
+                break;
+
+            case CONFIGURATION:
+                result = (T) new JPACPlainAttrUniqueValue();
+                break;
+
+            default:
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends AttrTemplate<PlainSchema>> Class<T> plainAttrTemplateClass() {
+        Class result;
+
+        switch (type) {
+            case ROLE:
+                result = JPARPlainAttrTemplate.class;
+                break;
+
+            case MEMBERSHIP:
+                result = JPAMPlainAttrTemplate.class;
+                break;
+
+            case USER:
+            case CONFIGURATION:
+            default:
+                result = null;
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends DerSchema> Class<T> derSchemaClass() {
+        Class result;
+
+        switch (type) {
+            case USER:
+                result = JPAUDerSchema.class;
+                break;
+
+            case ROLE:
+                result = JPARDerSchema.class;
+                break;
+
+            case MEMBERSHIP:
+                result = JPAMDerSchema.class;
+                break;
+
+            case CONFIGURATION:
+            default:
+                result = null;
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends DerSchema> T newDerSchema() {
+        T result = null;
+
+        switch (type) {
+            case USER:
+                result = (T) new JPAUDerSchema();
+                break;
+
+            case ROLE:
+                result = (T) new JPARDerSchema();
+                break;
+
+            case MEMBERSHIP:
+                result = (T) new JPAMDerSchema();
+                break;
+
+            case CONFIGURATION:
+            default:
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends DerAttr> Class<T> derAttrClass() {
+        Class result = null;
+
+        switch (type) {
+            case USER:
+                result = JPAUDerAttr.class;
+                break;
+
+            case ROLE:
+                result = JPARDerAttr.class;
+                break;
+
+            case MEMBERSHIP:
+                result = JPAMDerAttr.class;
+                break;
+
+            case CONFIGURATION:
+            default:
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends DerAttr> T newDerAttr() {
+        T result = null;
+
+        switch (type) {
+            case USER:
+                result = (T) new JPAUDerAttr();
+                break;
+
+            case ROLE:
+                result = (T) new JPARDerAttr();
+                break;
+
+            case MEMBERSHIP:
+                result = (T) new JPAMDerAttr();
+                break;
+
+            case CONFIGURATION:
+            default:
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends AttrTemplate<DerSchema>> Class<T> derAttrTemplateClass() {
+        Class result = null;
+
+        switch (type) {
+            case USER:
+                break;
+
+            case ROLE:
+                result = JPARDerAttrTemplate.class;
+                break;
+
+            case MEMBERSHIP:
+                result = JPAMDerAttrTemplate.class;
+                break;
+
+            case CONFIGURATION:
+            default:
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends VirSchema> Class<T> virSchemaClass() {
+        Class result = null;
+
+        switch (type) {
+            case USER:
+                result = JPAUVirSchema.class;
+                break;
+
+            case ROLE:
+                result = JPARVirSchema.class;
+                break;
+
+            case MEMBERSHIP:
+                result = JPAMVirSchema.class;
+                break;
+
+            case CONFIGURATION:
+            default:
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends VirSchema> T newVirSchema() {
+        T result = null;
+
+        switch (type) {
+            case USER:
+                result = (T) new JPAUVirSchema();
+                break;
+
+            case ROLE:
+                result = (T) new JPARVirSchema();
+                break;
+
+            case MEMBERSHIP:
+                result = (T) new JPAMVirSchema();
+                break;
+
+            case CONFIGURATION:
+            default:
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends VirAttr> Class<T> virAttrClass() {
+        Class result = null;
+
+        switch (type) {
+            case USER:
+                result = JPAUVirAttr.class;
+                break;
+
+            case ROLE:
+                result = JPARVirAttr.class;
+                break;
+
+            case MEMBERSHIP:
+                result = JPAMVirAttr.class;
+                break;
+
+            case CONFIGURATION:
+            default:
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends VirAttr> T newVirAttr() {
+        T result = null;
+
+        switch (type) {
+            case USER:
+                result = (T) new JPAUVirAttr();
+                break;
+
+            case ROLE:
+                result = (T) new JPARVirAttr();
+                break;
+
+            case MEMBERSHIP:
+                result = (T) new JPAMVirAttr();
+                break;
+
+            case CONFIGURATION:
+            default:
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends AttrTemplate<VirSchema>> Class<T> virAttrTemplateClass() {
+        Class result = null;
+
+        switch (type) {
+            case USER:
+                break;
+
+            case ROLE:
+                result = JPARVirAttrTemplate.class;
+                break;
+
+            case MEMBERSHIP:
+                result = JPAMVirAttrTemplate.class;
+                break;
+
+            case CONFIGURATION:
+            default:
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends MappingItem> T getAccountIdItem(final ExternalResource resource) {
+        T result = null;
+
+        if (resource != null) {
+            switch (type) {
+                case ROLE:
+                    if (resource.getRmapping() != null) {
+                        result = (T) resource.getRmapping().getAccountIdItem();
+                    }
+                    break;
+
+                case MEMBERSHIP:
+                case USER:
+                    if (resource.getUmapping() != null) {
+                        result = (T) resource.getUmapping().getAccountIdItem();
+                    }
+                    break;
+
+                default:
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public String getAccountLink(final ExternalResource resource) {
+        String result = null;
+
+        if (resource != null) {
+            switch (type) {
+                case USER:
+                    if (resource.getUmapping() != null) {
+                        result = resource.getUmapping().getAccountLink();
+                    }
+                    break;
+
+                case ROLE:
+                    if (resource.getRmapping() != null) {
+                        result = resource.getRmapping().getAccountLink();
+                    }
+                    break;
+
+                case MEMBERSHIP:
+                case CONFIGURATION:
+                default:
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends MappingItem> List<T> getMappingItems(
+            final ExternalResource resource, final MappingPurpose purpose) {
+
+        List<T> items = Collections.<T>emptyList();
+
+        if (resource != null) {
+            switch (type) {
+                case ROLE:
+                    if (resource.getRmapping() != null) {
+                        items = (List<T>) resource.getRmapping().getItems();
+                    }
+                    break;
+
+                case MEMBERSHIP:
+                case USER:
+                    if (resource.getUmapping() != null) {
+                        items = (List<T>) resource.getUmapping().getItems();
+                    }
+                    break;
+
+                default:
+            }
+        }
+
+        final List<T> result = new ArrayList<T>();
+
+        switch (purpose) {
+            case SYNCHRONIZATION:
+                for (T item : items) {
+                    if (MappingPurpose.PROPAGATION != item.getPurpose()
+                            && MappingPurpose.NONE != item.getPurpose()) {
+
+                        result.add(item);
+                    }
+                }
+                break;
+
+            case PROPAGATION:
+                for (T item : items) {
+                    if (MappingPurpose.SYNCHRONIZATION != item.getPurpose()
+                            && MappingPurpose.NONE != item.getPurpose()) {
+
+                        result.add(item);
+                    }
+                }
+                break;
+
+            case BOTH:
+                for (T item : items) {
+                    if (MappingPurpose.NONE != item.getPurpose()) {
+                        result.add(item);
+                    }
+                }
+                break;
+
+            case NONE:
+                for (T item : items) {
+                    if (MappingPurpose.NONE == item.getPurpose()) {
+                        result.add(item);
+                    }
+                }
+                break;
+            default:
+                LOG.error("You requested not existing purpose {}", purpose);
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends MappingItem> List<T> getUidToMappingItems(
+            final ExternalResource resource, final MappingPurpose purpose) {
+
+        List<T> items = getMappingItems(resource, purpose);
+
+        MappingItem uidItem = type == AttributableType.USER ? new JPAUMappingItem() : new JPARMappingItem();
+        BeanUtils.copyProperties(getAccountIdItem(resource), uidItem);
+        uidItem.setExtAttrName(Uid.NAME);
+        uidItem.setAccountid(false);
+        items.add((T) uidItem);
+
+        return items;
+    }
+
+    @Override
+    public IntMappingType intMappingType() {
+        IntMappingType result = null;
+
+        switch (type) {
+            case ROLE:
+                result = IntMappingType.RoleSchema;
+                break;
+
+            case MEMBERSHIP:
+                result = IntMappingType.MembershipSchema;
+                break;
+
+            case USER:
+                result = IntMappingType.UserSchema;
+                break;
+
+            case CONFIGURATION:
+            default:
+        }
+
+        return result;
+    }
+
+    @Override
+    public IntMappingType derIntMappingType() {
+        IntMappingType result = null;
+
+        switch (type) {
+            case ROLE:
+                result = IntMappingType.RoleSchema;
+                break;
+
+            case MEMBERSHIP:
+                result = IntMappingType.MembershipSchema;
+                break;
+
+            case USER:
+                result = IntMappingType.UserSchema;
+                break;
+
+            case CONFIGURATION:
+            default:
+        }
+
+        return result;
+    }
+
+    @Override
+    public IntMappingType virIntMappingType() {
+        IntMappingType result = null;
+
+        switch (type) {
+            case ROLE:
+                result = IntMappingType.RoleVirtualSchema;
+                break;
+
+            case MEMBERSHIP:
+                result = IntMappingType.MembershipVirtualSchema;
+                break;
+
+            case USER:
+                result = IntMappingType.UserVirtualSchema;
+                break;
+
+            case CONFIGURATION:
+            default:
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends MappingItem> Class<T> mappingItemClass() {
+        Class result = null;
+
+        switch (type) {
+            case USER:
+                result = JPAUMappingItem.class;
+                break;
+
+            case ROLE:
+                result = JPARMappingItem.class;
+                break;
+
+            case MEMBERSHIP:
+                result = AbstractMappingItem.class;
+                break;
+
+            case CONFIGURATION:
+            default:
+        }
+
+        return result;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAConnInstance.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAConnInstance.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAConnInstance.java
new file mode 100644
index 0000000..271f899
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAConnInstance.java
@@ -0,0 +1,268 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.persistence.CascadeType;
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.Lob;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.types.ConnConfProperty;
+import org.apache.syncope.common.lib.types.ConnectorCapability;
+import org.apache.syncope.persistence.api.entity.ConnInstance;
+import org.apache.syncope.persistence.api.entity.ConnPoolConf;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.jpa.validation.entity.ConnInstanceCheck;
+import org.apache.syncope.server.utils.serialization.POJOHelper;
+
+@Entity
+@Table(name = JPAConnInstance.TABLE)
+@ConnInstanceCheck
+public class JPAConnInstance extends AbstractEntity<Long> implements ConnInstance {
+
+    private static final long serialVersionUID = -2294708794497208872L;
+
+    public static final String TABLE = "ConnInstance";
+
+    private static final int DEFAULT_TIMEOUT = 10;
+
+    @Id
+    private Long id;
+
+    /**
+     * URI identifying the local / remote ConnId location where the related connector bundle is found.
+     */
+    @Column(nullable = false)
+    private String location;
+
+    /**
+     * Connector bundle class name.
+     * Within a given location, the triple
+     * (ConnectorBundle-Name, ConnectorBundle-Version, ConnectorBundle-Version) must be unique.
+     */
+    @Column(nullable = false)
+    private String connectorName;
+
+    /**
+     * Qualified name for the connector bundle.
+     * Within a given location, the triple
+     * (ConnectorBundle-Name, ConnectorBundle-Version, ConnectorBundle-Version) must be unique.
+     */
+    @Column(nullable = false)
+    private String bundleName;
+
+    /**
+     * Version of the bundle.
+     * Within a given location, the triple
+     * (ConnectorBundle-Name, ConnectorBundle-Version, ConnectorBundle-Version) must be unique.
+     */
+    @Column(nullable = false)
+    private String version;
+
+    /**
+     * The set of capabilities supported by this connector instance.
+     */
+    @ElementCollection(fetch = FetchType.EAGER)
+    @Enumerated(EnumType.STRING)
+    @Column(name = "capabilities")
+    @CollectionTable(name = "ConnInstance_capabilities",
+            joinColumns =
+            @JoinColumn(name = "ConnInstance_id", referencedColumnName = "id"))
+    private Set<ConnectorCapability> capabilities;
+
+    /**
+     * The main configuration for the connector instance. This is directly implemented by the Configuration bean class
+     * which contains annotated ConfigurationProperties.
+     *
+     * @see org.identityconnectors.framework.api.ConfigurationProperty
+     */
+    @Lob
+    private String jsonConf;
+
+    @Column(unique = true)
+    private String displayName;
+
+    /**
+     * External resources associated to the connector.
+     */
+    @OneToMany(cascade = { CascadeType.ALL }, mappedBy = "connector")
+    private List<JPAExternalResource> resources;
+
+    /**
+     * Connector request timeout. It is not applied in case of sync, full reconciliation and search.
+     * DEFAULT_TIMEOUT is the default value to be used in case of unspecified timeout.
+     */
+    private Integer connRequestTimeout = DEFAULT_TIMEOUT;
+
+    private JPAConnPoolConf poolConf;
+
+    public JPAConnInstance() {
+        super();
+
+        capabilities = new HashSet<>();
+        resources = new ArrayList<>();
+    }
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public String getLocation() {
+        return location;
+    }
+
+    @Override
+    public void setLocation(final String location) {
+        this.location = location;
+    }
+
+    @Override
+    public String getConnectorName() {
+        return connectorName;
+    }
+
+    @Override
+    public void setConnectorName(final String connectorName) {
+        this.connectorName = connectorName;
+    }
+
+    @Override
+    public String getBundleName() {
+        return bundleName;
+    }
+
+    @Override
+    public void setBundleName(final String bundleName) {
+        this.bundleName = bundleName;
+    }
+
+    @Override
+    public String getVersion() {
+        return version;
+    }
+
+    @Override
+    public void setVersion(final String version) {
+        this.version = version;
+    }
+
+    @Override
+    public Set<ConnConfProperty> getConfiguration() {
+        Set<ConnConfProperty> configuration = Collections.<ConnConfProperty>emptySet();
+        if (!StringUtils.isBlank(jsonConf)) {
+            ConnConfProperty[] deserialized = POJOHelper.deserialize(jsonConf, ConnConfProperty[].class);
+            if (ArrayUtils.isNotEmpty(deserialized)) {
+                configuration = new HashSet<ConnConfProperty>(Arrays.asList(deserialized));
+            }
+        }
+
+        return configuration;
+    }
+
+    @Override
+    public void setConfiguration(final Set<ConnConfProperty> configuration) {
+        jsonConf = POJOHelper.serialize(new HashSet<ConnConfProperty>(configuration));
+    }
+
+    @Override
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    @Override
+    public void setDisplayName(final String displayName) {
+        this.displayName = displayName;
+    }
+
+    @Override
+    public List<? extends ExternalResource> getResources() {
+        return this.resources;
+    }
+
+    @Override
+    public boolean addResource(final ExternalResource resource) {
+        checkType(resource, JPAExternalResource.class);
+        return this.resources.contains((JPAExternalResource) resource)
+                || this.resources.add((JPAExternalResource) resource);
+    }
+
+    @Override
+    public boolean removeResource(final ExternalResource resource) {
+        checkType(resource, JPAExternalResource.class);
+        return this.resources.remove((JPAExternalResource) resource);
+    }
+
+    @Override
+    public boolean addCapability(final ConnectorCapability capabitily) {
+        return capabilities.add(capabitily);
+    }
+
+    @Override
+    public boolean removeCapability(final ConnectorCapability capabitily) {
+        return capabilities.remove(capabitily);
+    }
+
+    @Override
+    public Set<ConnectorCapability> getCapabilities() {
+        return capabilities;
+    }
+
+    @Override
+    public Integer getConnRequestTimeout() {
+        // DEFAULT_TIMEOUT will be returned in case of null timeout:
+        // * instances created by the content loader 
+        // * or with a timeout nullified explicitely
+        return connRequestTimeout == null ? DEFAULT_TIMEOUT : connRequestTimeout;
+    }
+
+    @Override
+    public void setConnRequestTimeout(final Integer timeout) {
+        this.connRequestTimeout = timeout;
+    }
+
+    @Override
+    public ConnPoolConf getPoolConf() {
+        return poolConf;
+    }
+
+    @Override
+    public void setPoolConf(final ConnPoolConf poolConf) {
+        checkType(poolConf, JPAConnPoolConf.class);
+        this.poolConf = (JPAConnPoolConf) poolConf;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAConnPoolConf.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAConnPoolConf.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAConnPoolConf.java
new file mode 100644
index 0000000..a7ed759
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAConnPoolConf.java
@@ -0,0 +1,107 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import java.io.Serializable;
+import javax.persistence.Embeddable;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.syncope.persistence.api.entity.ConnPoolConf;
+
+@Embeddable
+public class JPAConnPoolConf implements ConnPoolConf, Serializable {
+
+    private static final long serialVersionUID = -34259572059178970L;
+
+    private Integer maxObjects;
+
+    private Integer minIdle;
+
+    private Integer maxIdle;
+
+    private Long maxWait;
+
+    private Long minEvictableIdleTimeMillis;
+
+    @Override
+    public Integer getMaxObjects() {
+        return maxObjects;
+    }
+
+    @Override
+    public void setMaxObjects(final Integer maxObjects) {
+        this.maxObjects = maxObjects;
+    }
+
+    @Override
+    public Integer getMinIdle() {
+        return minIdle;
+    }
+
+    @Override
+    public void setMinIdle(final Integer minIdle) {
+        this.minIdle = minIdle;
+    }
+
+    @Override
+    public Integer getMaxIdle() {
+        return maxIdle;
+    }
+
+    @Override
+    public void setMaxIdle(final Integer maxIdle) {
+        this.maxIdle = maxIdle;
+    }
+
+    @Override
+    public Long getMaxWait() {
+        return maxWait;
+    }
+
+    @Override
+    public void setMaxWait(final Long maxWait) {
+        this.maxWait = maxWait;
+    }
+
+    @Override
+    public Long getMinEvictableIdleTimeMillis() {
+        return minEvictableIdleTimeMillis;
+    }
+
+    @Override
+    public void setMinEvictableIdleTimeMillis(final Long minEvictableIdleTimeMillis) {
+        this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
+    }
+
+    @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 ToStringBuilder.reflectionToString(this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAEntitlement.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAEntitlement.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAEntitlement.java
new file mode 100644
index 0000000..f96f4bc
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAEntitlement.java
@@ -0,0 +1,62 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import javax.persistence.Cacheable;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.Entitlement;
+
+@Entity
+@Table(name = JPAEntitlement.TABLE)
+@Cacheable
+public class JPAEntitlement extends AbstractEntity<String> implements Entitlement {
+
+    private static final long serialVersionUID = 8044745999246422483L;
+
+    public static final String TABLE = "Entitlement";
+
+    @Id
+    private String name;
+
+    @Column(nullable = true)
+    private String description;
+
+    @Override
+    public String getKey() {
+        return name;
+    }
+
+    @Override
+    public void setKey(final String key) {
+        this.name = key;
+    }
+
+    @Override
+    public String getDescription() {
+        return description;
+    }
+
+    @Override
+    public void setDescription(final String description) {
+        this.description = description;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAExternalResource.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAExternalResource.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAExternalResource.java
new file mode 100644
index 0000000..2b055bd
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAExternalResource.java
@@ -0,0 +1,426 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.Lob;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+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.persistence.api.entity.AccountPolicy;
+import org.apache.syncope.persistence.api.entity.ConnInstance;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.PasswordPolicy;
+import org.apache.syncope.persistence.api.entity.SyncPolicy;
+import org.apache.syncope.persistence.api.entity.role.RMapping;
+import org.apache.syncope.persistence.api.entity.user.UMapping;
+import org.apache.syncope.persistence.jpa.validation.entity.ExternalResourceCheck;
+import org.apache.syncope.persistence.jpa.entity.role.JPARMapping;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUMapping;
+import org.apache.syncope.server.utils.serialization.POJOHelper;
+import org.identityconnectors.framework.common.objects.SyncToken;
+
+/**
+ * Resource for propagation and synchronization.
+ */
+@Entity
+@Table(name = JPAExternalResource.TABLE)
+@ExternalResourceCheck
+public class JPAExternalResource extends AbstractAnnotatedEntity<String> implements ExternalResource {
+
+    private static final long serialVersionUID = -6937712883512073278L;
+
+    public static final String TABLE = "ExternalResource";
+
+    /**
+     * The resource identifier is the name.
+     */
+    @Id
+    private String name;
+
+    /**
+     * Should this resource enforce the mandatory constraints?
+     */
+    @Column(nullable = false)
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer enforceMandatoryCondition;
+
+    /**
+     * The resource type is identified by the associated connector.
+     */
+    @ManyToOne(fetch = FetchType.EAGER, cascade = { CascadeType.MERGE })
+    @NotNull
+    private JPAConnInstance connector;
+
+    /**
+     * Mapping for user objects.
+     */
+    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "resource")
+    private JPAUMapping umapping;
+
+    /**
+     * Mapping for role objects.
+     */
+    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "resource")
+    private JPARMapping rmapping;
+
+    /**
+     * Is this resource primary, for propagations?
+     */
+    @Column(nullable = false)
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer propagationPrimary;
+
+    /**
+     * Priority index for propagation ordering.
+     */
+    @Column(nullable = false)
+    private Integer propagationPriority;
+
+    /**
+     * Generate random password for propagation, if not provided?
+     */
+    @Column(nullable = false)
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer randomPwdIfNotProvided;
+
+    @Enumerated(EnumType.STRING)
+    @Column(nullable = false)
+    private PropagationMode propagationMode;
+
+    @Enumerated(EnumType.STRING)
+    @Column(nullable = false)
+    private TraceLevel createTraceLevel;
+
+    @Enumerated(EnumType.STRING)
+    @Column(nullable = false)
+    private TraceLevel updateTraceLevel;
+
+    @Enumerated(EnumType.STRING)
+    @Column(nullable = false)
+    private TraceLevel deleteTraceLevel;
+
+    @Enumerated(EnumType.STRING)
+    @Column(nullable = false)
+    private TraceLevel syncTraceLevel;
+
+    @ManyToOne(fetch = FetchType.EAGER, optional = true)
+    private JPAPasswordPolicy passwordPolicy;
+
+    @ManyToOne(fetch = FetchType.EAGER, optional = true)
+    private JPAAccountPolicy accountPolicy;
+
+    @ManyToOne(fetch = FetchType.EAGER, optional = true)
+    private JPASyncPolicy syncPolicy;
+
+    /**
+     * Configuration properties that are overridden from the connector instance.
+     */
+    @Lob
+    private String jsonConf;
+
+    /**
+     * SyncToken for calling ConnId's sync() on users.
+     */
+    @Lob
+    private String userializedSyncToken;
+
+    /**
+     * SyncToken for calling ConnId's sync() on roles.
+     */
+    @Lob
+    private String rserializedSyncToken;
+
+    /**
+     * (Optional) classes for PropagationAction.
+     */
+    @ElementCollection(fetch = FetchType.EAGER)
+    @Column(name = "action")
+    @CollectionTable(name = "ExternalResource_PropActions",
+            joinColumns =
+            @JoinColumn(name = "ExternalResource_name", referencedColumnName = "name"))
+    private List<String> propagationActionsClassNames = new ArrayList<>();
+
+    /**
+     * Default constructor.
+     */
+    public JPAExternalResource() {
+        super();
+
+        enforceMandatoryCondition = getBooleanAsInteger(false);
+        propagationPrimary = 0;
+        propagationPriority = 0;
+        randomPwdIfNotProvided = 0;
+        propagationMode = PropagationMode.TWO_PHASES;
+
+        createTraceLevel = TraceLevel.FAILURES;
+        updateTraceLevel = TraceLevel.FAILURES;
+        deleteTraceLevel = TraceLevel.FAILURES;
+        syncTraceLevel = TraceLevel.FAILURES;
+    }
+
+    @Override
+    public boolean isEnforceMandatoryCondition() {
+        return isBooleanAsInteger(enforceMandatoryCondition);
+    }
+
+    @Override
+    public void setEnforceMandatoryCondition(boolean enforceMandatoryCondition) {
+        this.enforceMandatoryCondition = getBooleanAsInteger(enforceMandatoryCondition);
+    }
+
+    @Override
+    public ConnInstance getConnector() {
+        return connector;
+    }
+
+    @Override
+    public void setConnector(final ConnInstance connector) {
+        checkType(connector, JPAConnInstance.class);
+        this.connector = (JPAConnInstance) connector;
+    }
+
+    @Override
+    public UMapping getUmapping() {
+        return umapping;
+    }
+
+    @Override
+    public void setUmapping(final UMapping umapping) {
+        checkType(umapping, JPAUMapping.class);
+        this.umapping = (JPAUMapping) umapping;
+    }
+
+    @Override
+    public RMapping getRmapping() {
+        return rmapping;
+    }
+
+    @Override
+    public void setRmapping(final RMapping rmapping) {
+        checkType(rmapping, JPARMapping.class);
+        this.rmapping = (JPARMapping) rmapping;
+    }
+
+    @Override
+    public boolean isPropagationPrimary() {
+        return isBooleanAsInteger(propagationPrimary);
+    }
+
+    @Override
+    public void setPropagationPrimary(boolean propagationPrimary) {
+        this.propagationPrimary = getBooleanAsInteger(propagationPrimary);
+    }
+
+    @Override
+    public Integer getPropagationPriority() {
+        return propagationPriority;
+    }
+
+    @Override
+    public void setPropagationPriority(Integer propagationPriority) {
+        if (propagationPriority != null) {
+            this.propagationPriority = propagationPriority;
+        }
+    }
+
+    @Override
+    public boolean isRandomPwdIfNotProvided() {
+        return isBooleanAsInteger(randomPwdIfNotProvided);
+    }
+
+    @Override
+    public void setRandomPwdIfNotProvided(boolean randomPwdIfNotProvided) {
+        this.randomPwdIfNotProvided = getBooleanAsInteger(randomPwdIfNotProvided);
+    }
+
+    @Override
+    public PropagationMode getPropagationMode() {
+        return propagationMode;
+    }
+
+    @Override
+    public void setPropagationMode(PropagationMode propagationMode) {
+        this.propagationMode = propagationMode;
+    }
+
+    @Override
+    public String getKey() {
+        return name;
+    }
+
+    @Override
+    public void setKey(final String name) {
+        this.name = name;
+    }
+
+    @Override
+    public TraceLevel getCreateTraceLevel() {
+        return createTraceLevel;
+    }
+
+    @Override
+    public void setCreateTraceLevel(final TraceLevel createTraceLevel) {
+        this.createTraceLevel = createTraceLevel;
+    }
+
+    @Override
+
+    public TraceLevel getDeleteTraceLevel() {
+        return deleteTraceLevel;
+    }
+
+    @Override
+    public void setDeleteTraceLevel(final TraceLevel deleteTraceLevel) {
+        this.deleteTraceLevel = deleteTraceLevel;
+    }
+
+    @Override
+    public TraceLevel getUpdateTraceLevel() {
+        return updateTraceLevel;
+    }
+
+    @Override
+    public void setUpdateTraceLevel(final TraceLevel updateTraceLevel) {
+        this.updateTraceLevel = updateTraceLevel;
+    }
+
+    @Override
+    public TraceLevel getSyncTraceLevel() {
+        return syncTraceLevel;
+    }
+
+    @Override
+    public void setSyncTraceLevel(final TraceLevel syncTraceLevel) {
+        this.syncTraceLevel = syncTraceLevel;
+    }
+
+    @Override
+    public AccountPolicy getAccountPolicy() {
+        return accountPolicy;
+    }
+
+    @Override
+    public void setAccountPolicy(final AccountPolicy accountPolicy) {
+        checkType(accountPolicy, JPAAccountPolicy.class);
+        this.accountPolicy = (JPAAccountPolicy) accountPolicy;
+    }
+
+    @Override
+    public PasswordPolicy getPasswordPolicy() {
+        return passwordPolicy;
+    }
+
+    @Override
+    public void setPasswordPolicy(final PasswordPolicy passwordPolicy) {
+        checkType(passwordPolicy, JPAPasswordPolicy.class);
+        this.passwordPolicy = (JPAPasswordPolicy) passwordPolicy;
+    }
+
+    @Override
+    public SyncPolicy getSyncPolicy() {
+        return syncPolicy;
+    }
+
+    @Override
+    public void setSyncPolicy(final SyncPolicy syncPolicy) {
+        checkType(syncPolicy, JPASyncPolicy.class);
+        this.syncPolicy = (JPASyncPolicy) syncPolicy;
+    }
+
+    @Override
+    public Set<ConnConfProperty> getConnInstanceConfiguration() {
+        return StringUtils.isBlank(jsonConf)
+                ? Collections.<ConnConfProperty>emptySet()
+                : new HashSet<>(Arrays.asList(POJOHelper.deserialize(jsonConf, ConnConfProperty[].class)));
+    }
+
+    @Override
+    public void setConnInstanceConfiguration(final Set<ConnConfProperty> properties) {
+        jsonConf = POJOHelper.serialize(new HashSet<>(properties));
+    }
+
+    @Override
+    public String getSerializedUSyncToken() {
+        return userializedSyncToken;
+    }
+
+    @Override
+    public SyncToken getUsyncToken() {
+        return userializedSyncToken == null
+                ? null
+                : POJOHelper.deserialize(userializedSyncToken, SyncToken.class);
+    }
+
+    @Override
+    public void setUsyncToken(final SyncToken syncToken) {
+        this.userializedSyncToken = syncToken == null ? null : POJOHelper.serialize(syncToken);
+    }
+
+    @Override
+    public String getSerializedRSyncToken() {
+        return rserializedSyncToken;
+    }
+
+    @Override
+    public SyncToken getRsyncToken() {
+        return rserializedSyncToken == null
+                ? null
+                : POJOHelper.deserialize(rserializedSyncToken, SyncToken.class);
+    }
+
+    @Override
+    public void setRsyncToken(final SyncToken syncToken) {
+        this.rserializedSyncToken = syncToken == null ? null : POJOHelper.serialize(syncToken);
+    }
+
+    @Override
+    public List<String> getPropagationActionsClassNames() {
+        return propagationActionsClassNames;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPALogger.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPALogger.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPALogger.java
new file mode 100644
index 0000000..c20856d
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPALogger.java
@@ -0,0 +1,80 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import org.apache.syncope.common.lib.types.LoggerLevel;
+import org.apache.syncope.common.lib.types.LoggerType;
+import org.apache.syncope.persistence.api.entity.Logger;
+
+@Entity
+@Table(name = JPALogger.TABLE)
+public class JPALogger extends AbstractEntity<String> implements Logger {
+
+    private static final long serialVersionUID = 943012777014416027L;
+
+    public static final String TABLE = "SyncopeLogger";
+
+    @Id
+    @Column(name = "logName")
+    private String name;
+
+    @Column(name = "logLevel", nullable = false)
+    @Enumerated(EnumType.STRING)
+    private LoggerLevel level;
+
+    @Column(name = "logType", nullable = false)
+    @Enumerated(EnumType.STRING)
+    private LoggerType type;
+
+    @Override
+    public String getKey() {
+        return name;
+    }
+
+    @Override
+    public void setKey(final String name) {
+        this.name = name;
+    }
+
+    @Override
+    public LoggerLevel getLevel() {
+        return level;
+    }
+
+    @Override
+    public void setLevel(final LoggerLevel level) {
+        this.level = level;
+    }
+
+    @Override
+    public LoggerType getType() {
+        return type;
+    }
+
+    @Override
+    public void setType(final LoggerType type) {
+        this.type = type;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPANotification.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPANotification.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPANotification.java
new file mode 100644
index 0000000..8f93dbd
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPANotification.java
@@ -0,0 +1,262 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Basic;
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.Table;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.TraceLevel;
+import org.apache.syncope.persistence.api.entity.Notification;
+import org.apache.syncope.persistence.jpa.validation.entity.NotificationCheck;
+
+@Entity
+@Table(name = JPANotification.TABLE)
+@NotificationCheck
+public class JPANotification extends AbstractEntity<Long> implements Notification {
+
+    private static final long serialVersionUID = 3112582296912757537L;
+
+    public static final String TABLE = "Notification";
+
+    @Id
+    private Long id;
+
+    @ElementCollection(fetch = FetchType.EAGER)
+    @CollectionTable(name = "Notification_events",
+            joinColumns =
+            @JoinColumn(name = "Notification_id", referencedColumnName = "id"))
+    @Column(name = "events")
+    private List<String> events;
+
+    private String userAbout;
+
+    private String roleAbout;
+
+    private String recipients;
+
+    @ElementCollection(fetch = FetchType.EAGER)
+    @CollectionTable(name = "Notification_staticRecipients",
+            joinColumns =
+            @JoinColumn(name = "Notification_id", referencedColumnName = "id"))
+    @Column(name = "staticRecipients")
+    private List<String> staticRecipients;
+
+    @NotNull
+    @Enumerated(EnumType.STRING)
+    private IntMappingType recipientAttrType;
+
+    @NotNull
+    private String recipientAttrName;
+
+    @Column(nullable = false)
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer selfAsRecipient;
+
+    @NotNull
+    private String sender;
+
+    @NotNull
+    private String subject;
+
+    @NotNull
+    private String template;
+
+    @NotNull
+    @Enumerated(EnumType.STRING)
+    private TraceLevel traceLevel;
+
+    @Column(nullable = false)
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer active;
+
+    public JPANotification() {
+        events = new ArrayList<>();
+        staticRecipients = new ArrayList<>();
+        selfAsRecipient = getBooleanAsInteger(false);
+        active = getBooleanAsInteger(true);
+        traceLevel = TraceLevel.ALL;
+    }
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public String getUserAbout() {
+        return userAbout;
+    }
+
+    @Override
+    public void setUserAbout(final String userAbout) {
+        this.userAbout = userAbout;
+    }
+
+    @Override
+    public String getRoleAbout() {
+        return roleAbout;
+    }
+
+    @Override
+    public void setRoleAbout(final String roleAbout) {
+        this.roleAbout = roleAbout;
+    }
+
+    @Override
+    public String getRecipients() {
+        return recipients;
+    }
+
+    @Override
+    public void setRecipients(final String recipients) {
+        this.recipients = recipients;
+    }
+
+    @Override
+    public String getRecipientAttrName() {
+        return recipientAttrName;
+    }
+
+    @Override
+    public void setRecipientAttrName(final String recipientAttrName) {
+        this.recipientAttrName = recipientAttrName;
+    }
+
+    @Override
+    public IntMappingType getRecipientAttrType() {
+        return recipientAttrType;
+    }
+
+    @Override
+
+    public void setRecipientAttrType(final IntMappingType recipientAttrType) {
+        this.recipientAttrType = recipientAttrType;
+    }
+
+    @Override
+    public List<String> getEvents() {
+        return events;
+    }
+
+    @Override
+    public boolean addEvent(final String event) {
+        return event != null && !events.contains(event) && events.add(event);
+    }
+
+    @Override
+    public boolean removeEvent(final String event) {
+        return event != null && events.remove(event);
+    }
+
+    @Override
+    public List<String> getStaticRecipients() {
+        return staticRecipients;
+    }
+
+    @Override
+    public boolean addStaticRecipient(final String staticRecipient) {
+        return staticRecipient != null && !staticRecipients.contains(staticRecipient)
+                && staticRecipients.add(staticRecipient);
+    }
+
+    @Override
+    public boolean removeStaticRecipient(final String staticRecipient) {
+        return staticRecipient != null && staticRecipients.remove(staticRecipient);
+    }
+
+    @Override
+    public boolean isSelfAsRecipient() {
+        return isBooleanAsInteger(selfAsRecipient);
+    }
+
+    @Override
+    public void setSelfAsRecipient(final boolean selfAsRecipient) {
+        this.selfAsRecipient = getBooleanAsInteger(selfAsRecipient);
+    }
+
+    @Override
+    public String getSender() {
+        return sender;
+    }
+
+    @Override
+    public void setSender(final String sender) {
+        this.sender = sender;
+    }
+
+    @Override
+    public String getSubject() {
+        return subject;
+    }
+
+    @Override
+
+    public void setSubject(final String subject) {
+        this.subject = subject;
+    }
+
+    @Override
+    public String getTemplate() {
+        return template;
+    }
+
+    @Override
+    public void setTemplate(final String template) {
+        this.template = template;
+    }
+
+    @Override
+    public TraceLevel getTraceLevel() {
+        return traceLevel;
+    }
+
+    @Override
+    public void setTraceLevel(final TraceLevel traceLevel) {
+        this.traceLevel = traceLevel;
+    }
+
+    @Override
+    public boolean isActive() {
+        return isBooleanAsInteger(active);
+    }
+
+    @Override
+    public void setActive(final boolean active) {
+        this.active = getBooleanAsInteger(active);
+    }
+}


[27/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAPlainAttrValueDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAPlainAttrValueDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAPlainAttrValueDAO.java
new file mode 100644
index 0000000..75951cb
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAPlainAttrValueDAO.java
@@ -0,0 +1,104 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.List;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.persistence.api.dao.PlainAttrValueDAO;
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.persistence.api.entity.conf.CPlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.conf.CPlainAttrValue;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttrValue;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttrValue;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttrValue;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainAttrValue;
+import org.apache.syncope.persistence.jpa.entity.conf.JPACPlainAttrUniqueValue;
+import org.apache.syncope.persistence.jpa.entity.conf.JPACPlainAttrValue;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMPlainAttrUniqueValue;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMPlainAttrValue;
+import org.apache.syncope.persistence.jpa.entity.role.JPARPlainAttrUniqueValue;
+import org.apache.syncope.persistence.jpa.entity.role.JPARPlainAttrValue;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUPlainAttrUniqueValue;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUPlainAttrValue;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class JPAPlainAttrValueDAO extends AbstractDAO<PlainAttrValue, Long> implements PlainAttrValueDAO {
+
+    private <T extends PlainAttrValue> Class<? extends AbstractPlainAttrValue> getJPAEntityReference(
+            final Class<T> reference) {
+
+        return reference.equals(CPlainAttrValue.class)
+                ? JPACPlainAttrValue.class
+                : reference.equals(CPlainAttrUniqueValue.class)
+                        ? JPACPlainAttrUniqueValue.class
+                        : reference.equals(RPlainAttrValue.class)
+                                ? JPARPlainAttrValue.class
+                                : reference.equals(RPlainAttrUniqueValue.class)
+                                        ? JPARPlainAttrUniqueValue.class
+                                        : reference.equals(MPlainAttrValue.class)
+                                                ? JPAMPlainAttrValue.class
+                                                : reference.equals(MPlainAttrUniqueValue.class)
+                                                        ? JPAMPlainAttrUniqueValue.class
+                                                        : reference.equals(UPlainAttrValue.class)
+                                                                ? JPAUPlainAttrValue.class
+                                                                : reference.equals(UPlainAttrUniqueValue.class)
+                                                                        ? JPAUPlainAttrUniqueValue.class
+                                                                        : null;
+    }
+
+    @Override
+    public <T extends PlainAttrValue> T find(final Long key, final Class<T> reference) {
+        return reference.cast(entityManager.find(getJPAEntityReference(reference), key));
+    }
+
+    @Override
+    public <T extends PlainAttrValue> List<T> findAll(final Class<T> reference) {
+        TypedQuery<T> query = entityManager.createQuery(
+                "SELECT e FROM " + getJPAEntityReference(reference).getSimpleName() + " e", reference);
+        return query.getResultList();
+    }
+
+    @Override
+    public <T extends PlainAttrValue> T save(final T attributeValue) {
+        return entityManager.merge(attributeValue);
+    }
+
+    @Override
+    public <T extends PlainAttrValue> void delete(final Long id, final Class<T> reference) {
+        T attributeValue = find(id, reference);
+        if (attributeValue == null) {
+            return;
+        }
+
+        delete(attributeValue);
+    }
+
+    @Override
+    public <T extends PlainAttrValue> void delete(final T attrValue) {
+        if (attrValue.getAttr() != null) {
+            attrValue.getAttr().removeValue(attrValue);
+        }
+
+        entityManager.remove(attrValue);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAPlainSchemaDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAPlainSchemaDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAPlainSchemaDAO.java
new file mode 100644
index 0000000..47c5127
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAPlainSchemaDAO.java
@@ -0,0 +1,141 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.persistence.api.dao.AttrTemplateDAO;
+import org.apache.syncope.persistence.api.dao.ExternalResourceDAO;
+import org.apache.syncope.persistence.api.dao.PlainAttrDAO;
+import org.apache.syncope.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.persistence.api.entity.AttributableUtil;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.apache.syncope.persistence.api.entity.conf.CPlainSchema;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttr;
+import org.apache.syncope.persistence.api.entity.membership.MPlainSchema;
+import org.apache.syncope.persistence.api.entity.role.RMappingItem;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttr;
+import org.apache.syncope.persistence.api.entity.role.RPlainSchema;
+import org.apache.syncope.persistence.api.entity.user.UMappingItem;
+import org.apache.syncope.persistence.api.entity.user.UPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.conf.JPACPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.role.JPARPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUPlainSchema;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class JPAPlainSchemaDAO extends AbstractDAO<PlainSchema, String> implements PlainSchemaDAO {
+
+    @Autowired
+    private PlainAttrDAO attrDAO;
+
+    @Autowired
+    private AttrTemplateDAO<PlainSchema> attrTemplateDAO;
+
+    @Autowired
+    private ExternalResourceDAO resourceDAO;
+
+    private <T extends PlainSchema> Class<? extends AbstractPlainSchema> getJPAEntityReference(
+            final Class<T> reference) {
+
+        return CPlainSchema.class.isAssignableFrom(reference)
+                ? JPACPlainSchema.class
+                : RPlainSchema.class.isAssignableFrom(reference)
+                        ? JPARPlainSchema.class
+                        : MPlainSchema.class.isAssignableFrom(reference)
+                                ? JPAMPlainSchema.class
+                                : UPlainSchema.class.isAssignableFrom(reference)
+                                        ? JPAUPlainSchema.class
+                                        : null;
+    }
+
+    @Override
+    public <T extends PlainSchema> T find(final String key, final Class<T> reference) {
+        return reference.cast(entityManager.find(getJPAEntityReference(reference), key));
+    }
+
+    @Override
+    public <T extends PlainSchema> List<T> findAll(final Class<T> reference) {
+        TypedQuery<T> query = entityManager.createQuery(
+                "SELECT e FROM " + getJPAEntityReference(reference).getSimpleName() + " e", reference);
+        return query.getResultList();
+    }
+
+    @Override
+    public <T extends PlainAttr> List<T> findAttrs(final PlainSchema schema, final Class<T> reference) {
+        final StringBuilder queryString = new StringBuilder("SELECT e FROM ").
+                append(((JPAPlainAttrDAO) attrDAO).getJPAEntityReference(reference).getSimpleName()).
+                append(" e WHERE e.");
+        if (RPlainAttr.class.isAssignableFrom(reference) || MPlainAttr.class.isAssignableFrom(reference)) {
+            queryString.append("template.");
+        }
+        queryString.append("schema=:schema");
+
+        TypedQuery<T> query = entityManager.createQuery(queryString.toString(), reference);
+        query.setParameter("schema", schema);
+
+        return query.getResultList();
+    }
+
+    @Override
+    public <T extends PlainSchema> T save(final T schema) {
+        return entityManager.merge(schema);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public void delete(final String key, final AttributableUtil attributableUtil) {
+        PlainSchema schema = find(key, attributableUtil.plainSchemaClass());
+        if (schema == null) {
+            return;
+        }
+
+        final Set<Long> attrIds = new HashSet<>();
+        for (PlainAttr attr : findAttrs(schema, attributableUtil.plainAttrClass())) {
+            attrIds.add(attr.getKey());
+        }
+        for (Long attrId : attrIds) {
+            attrDAO.delete(attrId, attributableUtil.plainAttrClass());
+        }
+
+        if (attributableUtil.getType() == AttributableType.ROLE
+                || attributableUtil.getType() == AttributableType.MEMBERSHIP) {
+
+            for (Iterator<Number> it = attrTemplateDAO.
+                    findBySchemaName(schema.getKey(), attributableUtil.plainAttrTemplateClass()).iterator();
+                    it.hasNext();) {
+
+                attrTemplateDAO.delete(it.next().longValue(), attributableUtil.plainAttrTemplateClass());
+            }
+        }
+
+        resourceDAO.deleteMapping(key, attributableUtil.intMappingType(), UMappingItem.class);
+        resourceDAO.deleteMapping(key, attributableUtil.intMappingType(), RMappingItem.class);
+
+        entityManager.remove(schema);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAPolicyDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAPolicyDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAPolicyDAO.java
new file mode 100644
index 0000000..d9aedce
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAPolicyDAO.java
@@ -0,0 +1,150 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.List;
+import javax.persistence.Query;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.dao.PolicyDAO;
+import org.apache.syncope.persistence.api.entity.AccountPolicy;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.PasswordPolicy;
+import org.apache.syncope.persistence.api.entity.Policy;
+import org.apache.syncope.persistence.api.entity.SyncPolicy;
+import org.apache.syncope.persistence.jpa.entity.JPAPolicy;
+import org.apache.syncope.persistence.jpa.entity.JPAAccountPolicy;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class JPAPolicyDAO extends AbstractDAO<Policy, Long> implements PolicyDAO {
+
+    @Override
+    @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");
+        query.setParameter("id", key);
+
+        List<T> result = query.getResultList();
+        return result.isEmpty()
+                ? null
+                : result.iterator().next();
+    }
+
+    @Override
+    @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");
+        query.setParameter("type", type);
+
+        return (List<T>) query.getResultList();
+    }
+
+    @Override
+    public List<AccountPolicy> findByResource(final ExternalResource resource) {
+        TypedQuery<AccountPolicy> query = entityManager.createQuery(
+                "SELECT e FROM " + JPAAccountPolicy.class.getSimpleName() + " e "
+                + "WHERE :resource MEMBER OF e.resources", AccountPolicy.class);
+        query.setParameter("resource", resource);
+
+        return query.getResultList();
+    }
+
+    @Override
+    public PasswordPolicy getGlobalPasswordPolicy() {
+        List<? extends Policy> policies = find(PolicyType.GLOBAL_PASSWORD);
+        return policies == null || policies.isEmpty()
+                ? null
+                : (PasswordPolicy) policies.get(0);
+    }
+
+    @Override
+    public AccountPolicy getGlobalAccountPolicy() {
+        List<? extends Policy> policies = find(PolicyType.GLOBAL_ACCOUNT);
+        return policies == null || policies.isEmpty()
+                ? null
+                : (AccountPolicy) policies.get(0);
+    }
+
+    @Override
+    public SyncPolicy getGlobalSyncPolicy() {
+        List<? extends Policy> policies = find(PolicyType.GLOBAL_SYNC);
+        return policies == null || policies.isEmpty()
+                ? null
+                : (SyncPolicy) policies.get(0);
+    }
+
+    @Override
+    public List<Policy> findAll() {
+        TypedQuery<Policy> query = entityManager.createQuery(
+                "SELECT e FROM " + JPAPolicy.class.getSimpleName() + " e", Policy.class);
+        return query.getResultList();
+    }
+
+    @Override
+    public <T extends Policy> T save(final T policy) {
+        switch (policy.getType()) {
+            case GLOBAL_PASSWORD:
+                // just one GLOBAL_PASSWORD policy
+                final PasswordPolicy passwordPolicy = getGlobalPasswordPolicy();
+
+                if (passwordPolicy != null && !passwordPolicy.getKey().equals(policy.getKey())) {
+                    throw new InvalidEntityException(PasswordPolicy.class, EntityViolationType.InvalidPasswordPolicy,
+                            "Global Password policy already exists");
+                }
+                break;
+
+            case GLOBAL_ACCOUNT:
+                // just one GLOBAL_ACCOUNT policy
+                final AccountPolicy accountPolicy = getGlobalAccountPolicy();
+
+                if (accountPolicy != null && !accountPolicy.getKey().equals(policy.getKey())) {
+                    throw new InvalidEntityException(PasswordPolicy.class, EntityViolationType.InvalidAccountPolicy,
+                            "Global Account policy already exists");
+                }
+                break;
+
+            case GLOBAL_SYNC:
+                // just one GLOBAL_SYNC policy
+                final SyncPolicy syncPolicy = getGlobalSyncPolicy();
+
+                if (syncPolicy != null && !syncPolicy.getKey().equals(policy.getKey())) {
+                    throw new InvalidEntityException(PasswordPolicy.class, EntityViolationType.InvalidSyncPolicy,
+                            "Global Synchronization policy already exists");
+                }
+                break;
+
+            case PASSWORD:
+            case ACCOUNT:
+            case SYNC:
+            default:
+        }
+
+        return entityManager.merge(policy);
+    }
+
+    @Override
+    public <T extends Policy> void delete(final T policy) {
+        entityManager.remove(policy);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAReportDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAReportDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAReportDAO.java
new file mode 100644
index 0000000..b398ae1
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAReportDAO.java
@@ -0,0 +1,90 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.Collections;
+import java.util.List;
+import javax.persistence.Query;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.persistence.api.dao.ReportDAO;
+import org.apache.syncope.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.entity.Report;
+import org.apache.syncope.persistence.jpa.entity.JPAReport;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+@Repository
+public class JPAReportDAO extends AbstractDAO<Report, Long> implements ReportDAO {
+
+    @Override
+    @Transactional(readOnly = true)
+    public Report find(final Long key) {
+        return entityManager.find(JPAReport.class, key);
+    }
+
+    @Override
+    public List<Report> findAll() {
+        return findAll(-1, -1, Collections.<OrderByClause>emptyList());
+    }
+
+    @Override
+    public List<Report> findAll(final int page, final int itemsPerPage, final List<OrderByClause> orderByClauses) {
+        final TypedQuery<Report> query = entityManager.createQuery(
+                "SELECT e FROM " + JPAReport.class.getSimpleName() + " e "
+                + toOrderByStatement(Report.class, "e", orderByClauses), Report.class);
+
+        query.setFirstResult(itemsPerPage * (page <= 0
+                ? 0
+                : page - 1));
+
+        if (itemsPerPage > 0) {
+            query.setMaxResults(itemsPerPage);
+        }
+
+        return query.getResultList();
+    }
+
+    @Override
+    public int count() {
+        Query countQuery = entityManager.createNativeQuery("SELECT COUNT(id) FROM " + JPAReport.TABLE);
+        return ((Number) countQuery.getSingleResult()).intValue();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Throwable.class)
+    public Report save(final Report report) throws InvalidEntityException {
+        return entityManager.merge(report);
+    }
+
+    @Override
+    public void delete(final Long key) {
+        Report report = find(key);
+        if (report == null) {
+            return;
+        }
+
+        delete(report);
+    }
+
+    @Override
+    public void delete(final Report report) {
+        entityManager.remove(report);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAReportExecDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAReportExecDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAReportExecDAO.java
new file mode 100644
index 0000000..d2ba1dc
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAReportExecDAO.java
@@ -0,0 +1,101 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.List;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.persistence.api.dao.ReportExecDAO;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.entity.Report;
+import org.apache.syncope.persistence.api.entity.ReportExec;
+import org.apache.syncope.persistence.jpa.entity.JPAReportExec;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+@Repository
+public class JPAReportExecDAO extends AbstractDAO<ReportExec, Long> implements ReportExecDAO {
+
+    @Override
+    public ReportExec find(final Long key) {
+        return entityManager.find(JPAReportExec.class, key);
+    }
+
+    private ReportExec findLatest(final Report report, final String field) {
+        TypedQuery<ReportExec> query = entityManager.createQuery(
+                "SELECT e FROM " + JPAReportExec.class.getSimpleName() + " e "
+                + "WHERE e.report=:report ORDER BY e." + field + " DESC", ReportExec.class);
+        query.setParameter("report", report);
+        query.setMaxResults(1);
+
+        List<ReportExec> result = query.getResultList();
+        return result == null || result.isEmpty()
+                ? null
+                : result.iterator().next();
+    }
+
+    @Override
+    public ReportExec findLatestStarted(final Report report) {
+        return findLatest(report, "startDate");
+    }
+
+    @Override
+    public ReportExec findLatestEnded(final Report report) {
+        return findLatest(report, "endDate");
+    }
+
+    @Override
+    public List<ReportExec> findAll() {
+        TypedQuery<ReportExec> query = entityManager.createQuery(
+                "SELECT e FROM " + JPAReportExec.class.getSimpleName() + " e", ReportExec.class);
+        return query.getResultList();
+    }
+
+    /**
+     * This method is annotated as transactional because called from ReportJob.
+     *
+     * @see org.apache.syncope.core.report.ReportJob
+     * @param execution to be merged
+     * @return merged execution
+     * @throws InvalidEntityException if any validation error occurs
+     */
+    @Override
+    @Transactional(rollbackFor = Throwable.class)
+    public ReportExec save(final ReportExec execution) throws InvalidEntityException {
+        return entityManager.merge(execution);
+    }
+
+    @Override
+    public void delete(final Long key) {
+        ReportExec execution = find(key);
+        if (execution == null) {
+            return;
+        }
+
+        delete(execution);
+    }
+
+    @Override
+    public void delete(final ReportExec execution) {
+        if (execution.getReport() != null) {
+            execution.getReport().removeExec(execution);
+        }
+
+        entityManager.remove(execution);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPARoleDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPARoleDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPARoleDAO.java
new file mode 100644
index 0000000..96174fe
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPARoleDAO.java
@@ -0,0 +1,531 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import javax.persistence.NoResultException;
+import javax.persistence.Query;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.syncope.persistence.api.RoleEntitlementUtil;
+import org.apache.syncope.persistence.api.dao.DerAttrDAO;
+import org.apache.syncope.persistence.api.dao.EntitlementDAO;
+import org.apache.syncope.persistence.api.dao.PlainAttrDAO;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.dao.VirAttrDAO;
+import org.apache.syncope.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.persistence.api.entity.AttrTemplate;
+import org.apache.syncope.persistence.api.entity.DerAttr;
+import org.apache.syncope.persistence.api.entity.Entitlement;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.Policy;
+import org.apache.syncope.persistence.api.entity.Subject;
+import org.apache.syncope.persistence.api.entity.VirAttr;
+import org.apache.syncope.persistence.api.entity.membership.MDerAttr;
+import org.apache.syncope.persistence.api.entity.membership.MDerAttrTemplate;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttr;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttrTemplate;
+import org.apache.syncope.persistence.api.entity.membership.MVirAttr;
+import org.apache.syncope.persistence.api.entity.membership.MVirAttrTemplate;
+import org.apache.syncope.persistence.api.entity.membership.Membership;
+import org.apache.syncope.persistence.api.entity.role.RDerAttr;
+import org.apache.syncope.persistence.api.entity.role.RDerAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttr;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttrValue;
+import org.apache.syncope.persistence.api.entity.role.RVirAttr;
+import org.apache.syncope.persistence.api.entity.role.RVirAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.entity.JPAAttributableUtil;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMembership;
+import org.apache.syncope.persistence.jpa.entity.role.JPARole;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+@Repository
+public class JPARoleDAO extends AbstractSubjectDAO<RPlainAttr, RDerAttr, RVirAttr> implements RoleDAO {
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Autowired
+    private PlainAttrDAO plainAttrDAO;
+
+    @Autowired
+    private DerAttrDAO derAttrDAO;
+
+    @Autowired
+    private VirAttrDAO virAttrDAO;
+
+    @Autowired
+    private EntitlementDAO entitlementDAO;
+
+    @Override
+    protected Subject<RPlainAttr, RDerAttr, RVirAttr> findInternal(final Long key) {
+        return find(key);
+    }
+
+    @Override
+    public Role find(final Long key) {
+        TypedQuery<Role> query = entityManager.createQuery(
+                "SELECT e FROM " + JPARole.class.getSimpleName() + " e WHERE e.id = :id", Role.class);
+        query.setParameter("id", key);
+
+        Role result = null;
+        try {
+            result = query.getSingleResult();
+        } catch (NoResultException e) {
+            LOG.debug("No role found with id {}", key, e);
+        }
+
+        return result;
+    }
+
+    @Override
+    public List<Role> find(final String name) {
+        TypedQuery<Role> query = entityManager.createQuery(
+                "SELECT e FROM " + JPARole.class.getSimpleName() + " e WHERE e.name = :name", Role.class);
+        query.setParameter("name", name);
+
+        return query.getResultList();
+    }
+
+    @Override
+    public Role find(final String name, final Long parentId) {
+        TypedQuery<Role> query;
+        if (parentId == null) {
+            query = entityManager.createQuery("SELECT r FROM " + JPARole.class.getSimpleName() + " r WHERE "
+                    + "r.name=:name AND r.parent IS NULL", Role.class);
+        } else {
+            query = entityManager.createQuery("SELECT r FROM " + JPARole.class.getSimpleName() + " r WHERE "
+                    + "r.name=:name AND r.parent.id=:parentId", Role.class);
+            query.setParameter("parentId", parentId);
+        }
+        query.setParameter("name", name);
+
+        List<Role> result = query.getResultList();
+        return result.isEmpty()
+                ? null
+                : result.get(0);
+    }
+
+    private void findSameOwnerDescendants(final List<Role> result, final Role role) {
+        List<Role> children = findChildren(role);
+        if (children != null) {
+            for (Role child : children) {
+                if ((child.getUserOwner() == null && child.getRoleOwner() == null && child.isInheritOwner())
+                        || (child.getUserOwner() != null && child.getUserOwner().equals(role.getUserOwner()))
+                        || (child.getRoleOwner() != null && child.getRoleOwner().equals(role.getRoleOwner()))) {
+
+                    findDescendants(result, child);
+                }
+            }
+        }
+        result.add(role);
+    }
+
+    @Transactional(readOnly = true)
+    @Override
+    public List<Role> findOwnedByUser(final Long userKey) {
+        User owner = userDAO.find(userKey);
+        if (owner == null) {
+            return Collections.<Role>emptyList();
+        }
+
+        StringBuilder queryString = new StringBuilder("SELECT e FROM ").append(JPARole.class.getSimpleName()).
+                append(" e WHERE e.userOwner=:owner ");
+        for (Long roleId : owner.getRoleIds()) {
+            queryString.append("OR e.roleOwner.id=").append(roleId).append(' ');
+        }
+
+        TypedQuery<Role> query = entityManager.createQuery(queryString.toString(), Role.class);
+        query.setParameter("owner", owner);
+
+        List<Role> result = new ArrayList<>();
+        for (Role role : query.getResultList()) {
+            findSameOwnerDescendants(result, role);
+        }
+
+        return result;
+    }
+
+    @Transactional(readOnly = true)
+    @Override
+    public List<Role> findOwnedByRole(final Long roleId) {
+        Role owner = find(roleId);
+        if (owner == null) {
+            return Collections.<Role>emptyList();
+        }
+
+        StringBuilder queryString = new StringBuilder("SELECT e FROM ").append(JPARole.class.getSimpleName()).
+                append(" e WHERE e.roleOwner=:owner ");
+
+        TypedQuery<Role> query = entityManager.createQuery(queryString.toString(), Role.class);
+        query.setParameter("owner", owner);
+
+        List<Role> result = new ArrayList<Role>();
+        for (Role role : query.getResultList()) {
+            findSameOwnerDescendants(result, role);
+        }
+
+        return result;
+    }
+
+    @Override
+    public List<Role> findByEntitlement(final Entitlement entitlement) {
+        TypedQuery<Role> query = entityManager.createQuery(
+                "SELECT e FROM " + JPARole.class.getSimpleName() + " e "
+                + "WHERE :entitlement MEMBER OF e.entitlements", Role.class);
+        query.setParameter("entitlement", entitlement);
+
+        return query.getResultList();
+    }
+
+    private Map.Entry<String, String> getPolicyFields(final PolicyType type) {
+        String policyField;
+        String inheritPolicyField;
+        if (type == PolicyType.GLOBAL_ACCOUNT || type == PolicyType.ACCOUNT) {
+            policyField = "accountPolicy";
+            inheritPolicyField = "inheritAccountPolicy";
+        } else {
+            policyField = "passwordPolicy";
+            inheritPolicyField = "inheritPasswordPolicy";
+        }
+
+        return new AbstractMap.SimpleEntry<>(policyField, inheritPolicyField);
+    }
+
+    private List<Role> findSamePolicyChildren(final Role role, final PolicyType type) {
+        List<Role> result = new ArrayList<Role>();
+
+        for (Role child : findChildren(role)) {
+            boolean inherit = type == PolicyType.GLOBAL_ACCOUNT || type == PolicyType.ACCOUNT
+                    ? child.isInheritAccountPolicy()
+                    : child.isInheritPasswordPolicy();
+            if (inherit) {
+                result.add(child);
+                result.addAll(findSamePolicyChildren(child, type));
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public List<Role> findByPolicy(final Policy policy) {
+        if (policy.getType() == PolicyType.GLOBAL_SYNC || policy.getType() == PolicyType.SYNC) {
+            return Collections.<Role>emptyList();
+        }
+
+        Map.Entry<String, String> policyFields = getPolicyFields(policy.getType());
+        StringBuilder queryString = new StringBuilder("SELECT e FROM ").
+                append(JPARole.class.getSimpleName()).append(" e WHERE e.").
+                append(policyFields.getKey()).append(" = :policy AND (e.").
+                append(policyFields.getValue()).append(" IS NULL OR e.").
+                append(policyFields.getValue()).append(" = 0)");
+
+        TypedQuery<Role> query = entityManager.createQuery(queryString.toString(), Role.class);
+        query.setParameter("policy", policy);
+
+        List<Role> result = new ArrayList<Role>();
+        for (Role role : query.getResultList()) {
+            result.add(role);
+            result.addAll(findSamePolicyChildren(role, policy.getType()));
+        }
+        return result;
+    }
+
+    @Override
+    public List<Role> findWithoutPolicy(final PolicyType type) {
+        if (type == PolicyType.GLOBAL_SYNC || type == PolicyType.SYNC) {
+            return Collections.<Role>emptyList();
+        }
+
+        Map.Entry<String, String> policyFields = getPolicyFields(type);
+        StringBuilder queryString = new StringBuilder("SELECT e FROM ").
+                append(JPARole.class.getSimpleName()).append(" e WHERE e.").
+                append(policyFields.getKey()).append(" IS NULL AND (e.").
+                append(policyFields.getValue()).append(" IS NULL OR e.").
+                append(policyFields.getValue()).append(" = 0)");
+
+        TypedQuery<Role> query = entityManager.createQuery(queryString.toString(), Role.class);
+        return query.getResultList();
+    }
+
+    private void findAncestors(final List<Role> result, final Role role) {
+        if (role.getParent() != null && !result.contains(role.getParent())) {
+            result.add(role.getParent());
+            findAncestors(result, role.getParent());
+        }
+    }
+
+    @Override
+    public List<Role> findAncestors(final Role role) {
+        List<Role> result = new ArrayList<>();
+        findAncestors(result, role);
+        return result;
+    }
+
+    @Override
+    public List<Role> findChildren(final Role role) {
+        TypedQuery<Role> query = entityManager.createQuery(
+                "SELECT r FROM " + JPARole.class.getSimpleName() + " r WHERE r.parent=:role", Role.class);
+        query.setParameter("role", role);
+
+        return query.getResultList();
+    }
+
+    private void findDescendants(final List<Role> result, final Role role) {
+        List<Role> children = findChildren(role);
+        if (children != null) {
+            for (Role child : children) {
+                findDescendants(result, child);
+            }
+        }
+        result.add(role);
+    }
+
+    @Override
+    public List<Role> findDescendants(final Role role) {
+        List<Role> result = new ArrayList<>();
+        findDescendants(result, role);
+        return result;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<Role> findByAttrValue(final String schemaName, final RPlainAttrValue attrValue) {
+        return (List<Role>) findByAttrValue(
+                schemaName, attrValue, JPAAttributableUtil.getInstance(AttributableType.ROLE));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Role findByAttrUniqueValue(final String schemaName, final RPlainAttrValue attrUniqueValue) {
+        return (Role) findByAttrUniqueValue(schemaName, attrUniqueValue,
+                JPAAttributableUtil.getInstance(AttributableType.ROLE));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<Role> findByDerAttrValue(final String schemaName, final String value) {
+        return (List<Role>) findByDerAttrValue(
+                schemaName, value, JPAAttributableUtil.getInstance(AttributableType.ROLE));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<Role> findByResource(final ExternalResource resource) {
+        return (List<Role>) findByResource(resource, JPAAttributableUtil.getInstance(AttributableType.ROLE));
+    }
+
+    @Override
+    public List<Role> findAll() {
+        return findAll(-1, -1, Collections.<OrderByClause>emptyList());
+    }
+
+    @Override
+    public List<Role> findAll(final int page, final int itemsPerPage, final List<OrderByClause> orderBy) {
+        TypedQuery<Role> query = entityManager.createQuery(
+                "SELECT e FROM " + JPARole.class.getSimpleName() + " e "
+                + toOrderByStatement(Role.class, "e", orderBy), Role.class);
+
+        query.setFirstResult(itemsPerPage * (page <= 0
+                ? 0
+                : page - 1));
+
+        if (itemsPerPage > 0) {
+            query.setMaxResults(itemsPerPage);
+        }
+
+        return query.getResultList();
+    }
+
+    @Override
+    public List<Membership> findMemberships(final Role role) {
+        TypedQuery<Membership> query = entityManager.createQuery(
+                "SELECT e FROM " + JPAMembership.class.getSimpleName() + " e"
+                + " WHERE e.role=:role", Membership.class);
+        query.setParameter("role", role);
+
+        return query.getResultList();
+    }
+
+    @SuppressWarnings("unchecked")
+    private List<Long> unmatched(final Long roleId,
+            final Class<?> attrClass, final Class<? extends AttrTemplate<?>> attrTemplateClass) {
+
+        final Query query = entityManager.createNativeQuery(new StringBuilder().
+                append("SELECT ma.id ").
+                append("FROM ").append(JPAMembership.TABLE).append(" m, ").
+                append(attrClass.getSimpleName()).append(" ma ").
+                append("WHERE m.role_id = ?1 ").
+                append("AND ma.owner_id = m.id ").
+                append("AND ma.template_id NOT IN (").
+                append("SELECT id ").
+                append("FROM ").append(attrTemplateClass.getSimpleName()).append(' ').
+                append("WHERE owner_id = ?1)").toString());
+        query.setParameter(1, roleId);
+
+        return query.getResultList();
+    }
+
+    @Override
+    public final int count() {
+        Query countQuery = entityManager.createNativeQuery(
+                "SELECT COUNT(e.id) FROM " + JPARole.TABLE + " e");
+
+        return ((Number) countQuery.getSingleResult()).intValue();
+    }
+
+    @Override
+    public Role save(final Role role) {
+        // reset account policy in case of inheritance
+        if (role.isInheritAccountPolicy()) {
+            role.setAccountPolicy(null);
+        }
+
+        // reset password policy in case of inheritance
+        if (role.isInheritPasswordPolicy()) {
+            role.setPasswordPolicy(null);
+        }
+
+        // remove attributes without a valid template
+        List<RPlainAttr> rToBeDeleted = new ArrayList<>();
+        for (PlainAttr attr : role.getPlainAttrs()) {
+            boolean found = false;
+            for (RPlainAttrTemplate template : role.findInheritedTemplates(RPlainAttrTemplate.class)) {
+                if (template.getSchema().equals(attr.getSchema())) {
+                    found = true;
+                }
+            }
+            if (!found) {
+                rToBeDeleted.add((RPlainAttr) attr);
+            }
+        }
+        for (RPlainAttr attr : rToBeDeleted) {
+            LOG.debug("Removing {} from {} because no template is available for it", attr, role);
+            role.removePlainAttr(attr);
+        }
+
+        // remove derived attributes without a valid template
+        List<RDerAttr> rDerToBeDeleted = new ArrayList<RDerAttr>();
+        for (DerAttr attr : role.getDerAttrs()) {
+            boolean found = false;
+            for (RDerAttrTemplate template : role.findInheritedTemplates(RDerAttrTemplate.class)) {
+                if (template.getSchema().equals(attr.getSchema())) {
+                    found = true;
+                }
+            }
+            if (!found) {
+                rDerToBeDeleted.add((RDerAttr) attr);
+            }
+        }
+        for (RDerAttr attr : rDerToBeDeleted) {
+            LOG.debug("Removing {} from {} because no template is available for it", attr, role);
+            role.removeDerAttr(attr);
+        }
+
+        // remove virtual attributes without a valid template
+        List<RVirAttr> rVirToBeDeleted = new ArrayList<RVirAttr>();
+        for (VirAttr attr : role.getVirAttrs()) {
+            boolean found = false;
+            for (RVirAttrTemplate template : role.findInheritedTemplates(RVirAttrTemplate.class)) {
+                if (template.getSchema().equals(attr.getSchema())) {
+                    found = true;
+                }
+            }
+            if (!found) {
+                LOG.debug("Removing {} from {} because no template is available for it", attr, role);
+                rVirToBeDeleted.add((RVirAttr) attr);
+            }
+        }
+        for (RVirAttr attr : rVirToBeDeleted) {
+            role.removeVirAttr(attr);
+        }
+
+        Role merged = entityManager.merge(role);
+
+        // Now the same process for any exising membership of the role being saved
+        if (role.getKey() != null) {
+            for (Long key : unmatched(role.getKey(), MPlainAttr.class, MPlainAttrTemplate.class)) {
+                LOG.debug("Removing MAttr[{}] because no template is available for it in {}", key, role);
+                plainAttrDAO.delete(key, MPlainAttr.class);
+            }
+            for (Long id : unmatched(role.getKey(), MDerAttr.class, MDerAttrTemplate.class)) {
+                LOG.debug("Removing MDerAttr[{}] because no template is available for it in {}", id, role);
+                derAttrDAO.delete(id, MDerAttr.class);
+            }
+            for (Long id : unmatched(role.getKey(), MVirAttr.class, MVirAttrTemplate.class)) {
+                LOG.debug("Removing MVirAttr[{}] because no template is available for it in {}", id, role);
+                virAttrDAO.delete(id, MVirAttr.class);
+            }
+        }
+
+        merged = entityManager.merge(merged);
+        for (VirAttr attr : merged.getVirAttrs()) {
+            attr.getValues().clear();
+            attr.getValues().addAll(role.getVirAttr(attr.getSchema().getKey()).getValues());
+        }
+
+        entitlementDAO.saveRoleEntitlement(merged);
+
+        return merged;
+    }
+
+    @Override
+    public void delete(final Role role) {
+        for (Role roleToBeDeleted : findDescendants(role)) {
+            for (Membership membership : findMemberships(roleToBeDeleted)) {
+                membership.getUser().removeMembership(membership);
+                userDAO.save(membership.getUser());
+
+                entityManager.remove(membership);
+            }
+
+            roleToBeDeleted.getEntitlements().clear();
+
+            roleToBeDeleted.setParent(null);
+            roleToBeDeleted.setUserOwner(null);
+            roleToBeDeleted.setRoleOwner(null);
+            entityManager.remove(roleToBeDeleted);
+
+            entitlementDAO.delete(RoleEntitlementUtil.getEntitlementNameFromRoleId(roleToBeDeleted.getKey()));
+        }
+    }
+
+    @Override
+    public void delete(final Long key) {
+        Role role = (Role) findInternal(key);
+        if (role == null) {
+            return;
+        }
+
+        delete(role);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPASecurityQuestionDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPASecurityQuestionDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPASecurityQuestionDAO.java
new file mode 100644
index 0000000..f17e7c0
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPASecurityQuestionDAO.java
@@ -0,0 +1,71 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.List;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.dao.SecurityQuestionDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.entity.user.SecurityQuestion;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.entity.JPASecurityQuestion;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class JPASecurityQuestionDAO extends AbstractDAO<SecurityQuestion, Long> implements SecurityQuestionDAO {
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Override
+    public SecurityQuestion find(final Long key) {
+        return entityManager.find(JPASecurityQuestion.class, key);
+    }
+
+    @Override
+    public List<SecurityQuestion> findAll() {
+        final TypedQuery<SecurityQuestion> query = entityManager.createQuery(
+                "SELECT e FROM " + JPASecurityQuestion.class.getSimpleName() + " e ", SecurityQuestion.class);
+        return query.getResultList();
+    }
+
+    @Override
+    public SecurityQuestion save(final SecurityQuestion securityQuestion) throws InvalidEntityException {
+        return entityManager.merge(securityQuestion);
+    }
+
+    @Override
+    public void delete(final Long key) {
+        SecurityQuestion securityQuestion = find(key);
+        if (securityQuestion == null) {
+            return;
+        }
+
+        for (User user : userDAO.findBySecurityQuestion(securityQuestion)) {
+            user.setSecurityQuestion(null);
+            user.setSecurityAnswer(null);
+            userDAO.save(user);
+        }
+
+        entityManager.remove(securityQuestion);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPASubjectSearchDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPASubjectSearchDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPASubjectSearchDAO.java
new file mode 100644
index 0000000..86e596f
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPASubjectSearchDAO.java
@@ -0,0 +1,715 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+import javax.persistence.Entity;
+import javax.persistence.Query;
+import javax.persistence.TemporalType;
+import javax.validation.ValidationException;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.SubjectType;
+import org.apache.syncope.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.dao.SubjectSearchDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.dao.search.AttributeCond;
+import org.apache.syncope.persistence.api.dao.search.EntitlementCond;
+import org.apache.syncope.persistence.api.dao.search.MembershipCond;
+import org.apache.syncope.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.persistence.api.dao.search.ResourceCond;
+import org.apache.syncope.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.persistence.api.dao.search.SubjectCond;
+import org.apache.syncope.persistence.api.entity.AttributableUtil;
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.apache.syncope.persistence.api.entity.Subject;
+import org.apache.syncope.persistence.jpa.entity.JPAAttributableUtil;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import org.springframework.util.ReflectionUtils;
+
+@Repository
+public class JPASubjectSearchDAO extends AbstractDAO<Subject<?, ?, ?>, Long> implements SubjectSearchDAO {
+
+    private static final String EMPTY_ATTR_QUERY = "SELECT subject_id FROM user_search_attr WHERE 1=2";
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Autowired
+    private RoleDAO roleDAO;
+
+    @Autowired
+    private PlainSchemaDAO schemaDAO;
+
+    private String getAdminRolesFilter(final Set<Long> adminRoles, final SubjectType type) {
+        final StringBuilder adminRolesFilter = new StringBuilder();
+
+        if (type == SubjectType.USER) {
+            adminRolesFilter.append("SELECT user_id AS subject_id FROM Membership M1 WHERE role_id IN (").
+                    append("SELECT role_id FROM Membership M2 WHERE M2.user_id=M1.user_id ").
+                    append("AND role_id NOT IN (");
+        }
+
+        adminRolesFilter.append("SELECT id AS ").
+                append(type == SubjectType.USER ? "role" : "subject").
+                append("_id FROM SyncopeRole");
+
+        boolean firstRole = true;
+
+        for (Long adminRoleId : adminRoles) {
+            if (firstRole) {
+                adminRolesFilter.append(" WHERE");
+                firstRole = false;
+            } else {
+                adminRolesFilter.append(type == SubjectType.USER ? " OR" : " AND");
+            }
+            adminRolesFilter.append(type == SubjectType.USER ? " id = " : " id <> ").append(adminRoleId);
+        }
+
+        if (type == SubjectType.USER) {
+            adminRolesFilter.append("))");
+        }
+
+        return adminRolesFilter.toString();
+    }
+
+    @Override
+    public int count(final Set<Long> adminRoles, final SearchCond searchCondition, final SubjectType type) {
+        List<Object> parameters = Collections.synchronizedList(new ArrayList<>());
+
+        // 1. get the query string from the search condition
+        SearchSupport svs = new SearchSupport(type);
+        StringBuilder queryString = getQuery(searchCondition, parameters, type, svs);
+
+        // 2. take into account administrative roles
+        queryString.insert(0, "SELECT u.subject_id FROM (");
+        queryString.append(") u WHERE subject_id NOT IN (");
+        queryString.append(getAdminRolesFilter(adminRoles, type)).append(')');
+
+        // 3. prepare the COUNT query
+        queryString.insert(0, "SELECT COUNT(subject_id) FROM (");
+        queryString.append(") count_subject_id");
+
+        Query countQuery = entityManager.createNativeQuery(queryString.toString());
+        fillWithParameters(countQuery, parameters);
+
+        LOG.debug("Native count query\n{}\nwith parameters\n{}", queryString.toString(), parameters);
+
+        int result = ((Number) countQuery.getSingleResult()).intValue();
+        LOG.debug("Native count query result: {}", result);
+
+        return result;
+    }
+
+    @Override
+    public <T extends Subject<?, ?, ?>> List<T> search(
+            final Set<Long> adminRoles, final SearchCond searchCondition, final SubjectType type) {
+
+        return search(adminRoles, searchCondition, Collections.<OrderByClause>emptyList(), type);
+    }
+
+    @Override
+    public <T extends Subject<?, ?, ?>> List<T> search(
+            final Set<Long> adminRoles, final SearchCond searchCondition, final List<OrderByClause> orderBy,
+            final SubjectType type) {
+
+        return search(adminRoles, searchCondition, -1, -1, orderBy, type);
+    }
+
+    @Override
+    public <T extends Subject<?, ?, ?>> List<T> search(
+            final Set<Long> adminRoles, final SearchCond searchCondition, final int page, final int itemsPerPage,
+            final List<OrderByClause> orderBy, final SubjectType type) {
+
+        List<T> result = Collections.<T>emptyList();
+
+        if (adminRoles != null && (!adminRoles.isEmpty() || roleDAO.findAll().isEmpty())) {
+            LOG.debug("Search condition:\n{}", searchCondition);
+
+            if (searchCondition != null && searchCondition.isValid()) {
+                try {
+                    result = doSearch(adminRoles, searchCondition, page, itemsPerPage, orderBy, type);
+                } catch (Exception e) {
+                    LOG.error("While searching for {}", type, e);
+                }
+            } else {
+                LOG.error("Invalid search condition:\n{}", searchCondition);
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends Subject<?, ?, ?>> boolean matches(
+            final T subject, final SearchCond searchCondition, final SubjectType type) {
+
+        List<Object> parameters = Collections.synchronizedList(new ArrayList<>());
+
+        // 1. get the query string from the search condition
+        SearchSupport svs = new SearchSupport(type);
+        StringBuilder queryString = getQuery(searchCondition, parameters, type, svs);
+
+        boolean matches;
+        if (queryString.length() == 0) {
+            // Could be empty: got into a role search with a single membership condition ...
+            matches = false;
+        } else {
+            // 2. take into account the passed user
+            queryString.insert(0, "SELECT u.subject_id FROM (");
+            queryString.append(") u WHERE subject_id=?").append(setParameter(parameters, subject.getKey()));
+
+            // 3. prepare the search query
+            Query query = entityManager.createNativeQuery(queryString.toString());
+
+            // 4. populate the search query with parameter values
+            fillWithParameters(query, parameters);
+
+            // 5. executes query
+            matches = !query.getResultList().isEmpty();
+        }
+
+        return matches;
+    }
+
+    private int setParameter(final List<Object> parameters, final Object parameter) {
+        int key;
+        synchronized (parameters) {
+            parameters.add(parameter);
+            key = parameters.size();
+        }
+
+        return key;
+    }
+
+    private void fillWithParameters(final Query query, final List<Object> parameters) {
+        for (int i = 0; i < parameters.size(); i++) {
+            if (parameters.get(i) instanceof Date) {
+                query.setParameter(i + 1, (Date) parameters.get(i), TemporalType.TIMESTAMP);
+            } else if (parameters.get(i) instanceof Boolean) {
+                query.setParameter(i + 1, ((Boolean) parameters.get(i))
+                        ? 1
+                        : 0);
+            } else {
+                query.setParameter(i + 1, parameters.get(i));
+            }
+        }
+    }
+
+    private StringBuilder buildSelect(final OrderBySupport orderBySupport) {
+        final StringBuilder select = new StringBuilder("SELECT u.subject_id");
+
+        for (OrderBySupport.Item obs : orderBySupport.items) {
+            select.append(',').append(obs.select);
+        }
+        select.append(" FROM ");
+
+        return select;
+    }
+
+    private StringBuilder buildWhere(final OrderBySupport orderBySupport, final SubjectType type) {
+        final StringBuilder where = new StringBuilder(" u");
+        for (SearchSupport.SearchView searchView : orderBySupport.views) {
+            where.append(',').append(searchView.name).append(' ').append(searchView.alias);
+        }
+        where.append(" WHERE ");
+        for (SearchSupport.SearchView searchView : orderBySupport.views) {
+            where.append("u.subject_id=").append(searchView.alias).append(".subject_id AND ");
+        }
+
+        for (OrderBySupport.Item obs : orderBySupport.items) {
+            if (StringUtils.isNotBlank(obs.where)) {
+                where.append(obs.where).append(" AND ");
+            }
+        }
+        where.append("u.subject_id NOT IN (");
+
+        return where;
+    }
+
+    private StringBuilder buildOrderBy(final OrderBySupport orderBySupport) {
+        final StringBuilder orderBy = new StringBuilder();
+
+        for (OrderBySupport.Item obs : orderBySupport.items) {
+            orderBy.append(obs.orderBy).append(',');
+        }
+        if (!orderBySupport.items.isEmpty()) {
+            orderBy.insert(0, " ORDER BY ");
+            orderBy.deleteCharAt(orderBy.length() - 1);
+        }
+
+        return orderBy;
+    }
+
+    private OrderBySupport parseOrderBy(final SubjectType type, final SearchSupport svs,
+            final List<OrderByClause> orderByClauses) {
+
+        final AttributableUtil attrUtil = JPAAttributableUtil.getInstance(type.asAttributableType());
+
+        OrderBySupport orderBySupport = new OrderBySupport();
+
+        for (OrderByClause clause : orderByClauses) {
+            OrderBySupport.Item obs = new OrderBySupport.Item();
+
+            Field subjectField = ReflectionUtils.findField(attrUtil.attributableClass(), clause.getField());
+            if (subjectField == null) {
+                PlainSchema schema = schemaDAO.find(clause.getField(), attrUtil.plainSchemaClass());
+                if (schema != null) {
+                    if (schema.isUniqueConstraint()) {
+                        orderBySupport.views.add(svs.uniqueAttr());
+
+                        obs.select = new StringBuilder().
+                                append(svs.uniqueAttr().alias).append('.').append(svs.fieldName(schema.getType())).
+                                append(" AS ").append(clause.getField()).toString();
+                        obs.where = new StringBuilder().
+                                append(svs.uniqueAttr().alias).
+                                append(".schema_name='").append(clause.getField()).append("'").toString();
+                        obs.orderBy = clause.getField() + " " + clause.getDirection().name();
+                    } else {
+                        orderBySupport.views.add(svs.attr());
+
+                        obs.select = new StringBuilder().
+                                append(svs.attr().alias).append('.').append(svs.fieldName(schema.getType())).
+                                append(" AS ").append(clause.getField()).toString();
+                        obs.where = new StringBuilder().
+                                append(svs.attr().alias).
+                                append(".schema_name='").append(clause.getField()).append("'").toString();
+                        obs.orderBy = clause.getField() + " " + clause.getDirection().name();
+                    }
+                }
+            } else {
+                orderBySupport.views.add(svs.field());
+
+                obs.select = svs.field().alias + "." + clause.getField();
+                obs.where = StringUtils.EMPTY;
+                obs.orderBy = svs.field().alias + "." + clause.getField() + " " + clause.getDirection().name();
+            }
+
+            if (obs.isEmpty()) {
+                LOG.warn("Cannot build any valid clause from {}", clause);
+            } else {
+                orderBySupport.items.add(obs);
+            }
+        }
+
+        return orderBySupport;
+    }
+
+    @SuppressWarnings("unchecked")
+    private <T extends Subject<?, ?, ?>> List<T> doSearch(final Set<Long> adminRoles,
+            final SearchCond nodeCond, final int page, final int itemsPerPage, final List<OrderByClause> orderBy,
+            final SubjectType type) {
+
+        List<Object> parameters = Collections.synchronizedList(new ArrayList<>());
+
+        // 1. get the query string from the search condition
+        SearchSupport svs = new SearchSupport(type);
+        StringBuilder queryString = getQuery(nodeCond, parameters, type, svs);
+
+        // 2. take into account administrative roles and ordering
+        OrderBySupport orderBySupport = parseOrderBy(type, svs, orderBy);
+        if (queryString.charAt(0) == '(') {
+            queryString.insert(0, buildSelect(orderBySupport));
+            queryString.append(buildWhere(orderBySupport, type));
+        } else {
+            queryString.insert(0, buildSelect(orderBySupport).append('('));
+            queryString.append(')').append(buildWhere(orderBySupport, type));
+        }
+        queryString.
+                append(getAdminRolesFilter(adminRoles, type)).append(')').
+                append(buildOrderBy(orderBySupport));
+
+        // 3. prepare the search query
+        Query query = entityManager.createNativeQuery(queryString.toString());
+
+        // 4. page starts from 1, while setFirtResult() starts from 0
+        query.setFirstResult(itemsPerPage * (page <= 0 ? 0 : page - 1));
+
+        if (itemsPerPage >= 0) {
+            query.setMaxResults(itemsPerPage);
+        }
+
+        // 5. populate the search query with parameter values
+        fillWithParameters(query, parameters);
+
+        LOG.debug("Native query\n{}\nwith parameters\n{}", queryString.toString(), parameters);
+
+        // 6. Prepare the result (avoiding duplicates)
+        List<T> result = new ArrayList<>();
+
+        for (Object subjectId : query.getResultList()) {
+            long actualId;
+            if (subjectId instanceof Object[]) {
+                actualId = ((Number) ((Object[]) subjectId)[0]).longValue();
+            } else {
+                actualId = ((Number) subjectId).longValue();
+            }
+
+            T subject = type == SubjectType.USER
+                    ? (T) userDAO.find(actualId)
+                    : (T) roleDAO.find(actualId);
+            if (subject == null) {
+                LOG.error("Could not find {} with id {}, even though returned by the native query",
+                        type, actualId);
+            } else {
+                if (!result.contains(subject)) {
+                    result.add(subject);
+                }
+            }
+        }
+
+        return result;
+    }
+
+    private StringBuilder getQuery(final SearchCond nodeCond, final List<Object> parameters,
+            final SubjectType type, final SearchSupport svs) {
+
+        StringBuilder query = new StringBuilder();
+
+        switch (nodeCond.getType()) {
+
+            case LEAF:
+            case NOT_LEAF:
+                if (nodeCond.getMembershipCond() != null && SubjectType.USER == type) {
+                    query.append(getQuery(nodeCond.getMembershipCond(),
+                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
+                }
+                if (nodeCond.getResourceCond() != null) {
+                    query.append(getQuery(nodeCond.getResourceCond(),
+                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, type, svs));
+                }
+                if (nodeCond.getEntitlementCond() != null) {
+                    query.append(getQuery(nodeCond.getEntitlementCond(),
+                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
+                }
+                if (nodeCond.getAttributeCond() != null) {
+                    query.append(getQuery(nodeCond.getAttributeCond(),
+                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, type, svs));
+                }
+                if (nodeCond.getSubjectCond() != null) {
+                    query.append(getQuery(nodeCond.getSubjectCond(),
+                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, type, svs));
+                }
+                break;
+
+            case AND:
+                query.append(getQuery(nodeCond.getLeftNodeCond(), parameters, type, svs)).
+                        append(" AND subject_id IN ( ").
+                        append(getQuery(nodeCond.getRightNodeCond(), parameters, type, svs)).
+                        append(")");
+                break;
+
+            case OR:
+                query.append(getQuery(nodeCond.getLeftNodeCond(), parameters, type, svs)).
+                        append(" OR subject_id IN ( ").
+                        append(getQuery(nodeCond.getRightNodeCond(), parameters, type, svs)).
+                        append(")");
+                break;
+
+            default:
+        }
+
+        return query;
+    }
+
+    private String getQuery(final MembershipCond cond, final boolean not, final List<Object> parameters,
+            final SearchSupport svs) {
+
+        StringBuilder query = new StringBuilder("SELECT DISTINCT subject_id FROM ").
+                append(svs.field().name).append(" WHERE ");
+
+        if (not) {
+            query.append("subject_id NOT IN (");
+        } else {
+            query.append("subject_id IN (");
+        }
+
+        query.append("SELECT DISTINCT subject_id ").append("FROM ").
+                append(svs.membership().name).append(" WHERE ").
+                append("role_id=?").append(setParameter(parameters, cond.getRoleId())).
+                append(')');
+
+        return query.toString();
+    }
+
+    private String getQuery(final ResourceCond cond, final boolean not, final List<Object> parameters,
+            final SubjectType type, final SearchSupport svs) {
+
+        final StringBuilder query = new StringBuilder("SELECT DISTINCT subject_id FROM ").
+                append(svs.field().name).append(" WHERE ");
+
+        if (not) {
+            query.append("subject_id NOT IN (");
+        } else {
+            query.append("subject_id IN (");
+        }
+
+        query.append("SELECT DISTINCT subject_id FROM ").
+                append(svs.resource().name).
+                append(" WHERE resource_name=?").
+                append(setParameter(parameters, cond.getResourceName()));
+
+        if (type == SubjectType.USER) {
+            query.append(" UNION SELECT DISTINCT subject_id FROM ").
+                    append(svs.roleResource().name).
+                    append(" WHERE resource_name=?").
+                    append(setParameter(parameters, cond.getResourceName()));
+        }
+
+        query.append(')');
+
+        return query.toString();
+    }
+
+    private String getQuery(final EntitlementCond cond, final boolean not, final List<Object> parameters,
+            final SearchSupport svs) {
+
+        final StringBuilder query = new StringBuilder("SELECT DISTINCT subject_id FROM ").
+                append(svs.entitlements().name).
+                append(" WHERE entitlement_name ");
+        if (not) {
+            query.append(" NOT ");
+        }
+        query.append(" LIKE ?").append(setParameter(parameters, cond.getExpression()));
+
+        return query.toString();
+    }
+
+    private void fillAttributeQuery(final StringBuilder query, final PlainAttrValue attrValue,
+            final PlainSchema schema, final AttributeCond cond, final boolean not,
+            final List<Object> parameters, final SearchSupport svs) {
+
+        String column = (cond instanceof SubjectCond)
+                ? cond.getSchema()
+                : "' AND " + svs.fieldName(schema.getType());
+
+        switch (cond.getType()) {
+
+            case ISNULL:
+                query.append(column).append(not
+                        ? " IS NOT NULL"
+                        : " IS NULL");
+                break;
+
+            case ISNOTNULL:
+                query.append(column).append(not
+                        ? " IS NULL"
+                        : " IS NOT NULL");
+                break;
+
+            case LIKE:
+                if (schema.getType() == AttrSchemaType.String || schema.getType() == AttrSchemaType.Enum) {
+                    query.append(column);
+                    if (not) {
+                        query.append(" NOT ");
+                    }
+                    query.append(" LIKE ?").append(setParameter(parameters, cond.getExpression()));
+                } else {
+                    if (!(cond instanceof SubjectCond)) {
+                        query.append("' AND");
+                    }
+                    query.append(" 1=2");
+                    LOG.error("LIKE is only compatible with string or enum schemas");
+                }
+                break;
+
+            case EQ:
+                query.append(column);
+                if (not) {
+                    query.append("<>");
+                } else {
+                    query.append('=');
+                }
+                query.append('?').append(setParameter(parameters, attrValue.getValue()));
+                break;
+
+            case GE:
+                query.append(column);
+                if (not) {
+                    query.append('<');
+                } else {
+                    query.append(">=");
+                }
+                query.append('?').append(setParameter(parameters, attrValue.getValue()));
+                break;
+
+            case GT:
+                query.append(column);
+                if (not) {
+                    query.append("<=");
+                } else {
+                    query.append('>');
+                }
+                query.append('?').append(setParameter(parameters, attrValue.getValue()));
+                break;
+
+            case LE:
+                query.append(column);
+                if (not) {
+                    query.append('>');
+                } else {
+                    query.append("<=");
+                }
+                query.append('?').append(setParameter(parameters, attrValue.getValue()));
+                break;
+
+            case LT:
+                query.append(column);
+                if (not) {
+                    query.append(">=");
+                } else {
+                    query.append('<');
+                }
+                query.append('?').append(setParameter(parameters, attrValue.getValue()));
+                break;
+
+            default:
+        }
+    }
+
+    private String getQuery(final AttributeCond cond, final boolean not, final List<Object> parameters,
+            final SubjectType type, final SearchSupport svs) {
+
+        final AttributableUtil attrUtil = JPAAttributableUtil.getInstance(type.asAttributableType());
+
+        PlainSchema schema = schemaDAO.find(cond.getSchema(), attrUtil.plainSchemaClass());
+        if (schema == null) {
+            LOG.warn("Ignoring invalid schema '{}'", cond.getSchema());
+            return EMPTY_ATTR_QUERY;
+        }
+
+        PlainAttrValue attrValue = attrUtil.newPlainAttrValue();
+        try {
+            if (cond.getType() != AttributeCond.Type.LIKE && cond.getType() != AttributeCond.Type.ISNULL
+                    && cond.getType() != AttributeCond.Type.ISNOTNULL) {
+
+                schema.getValidator().validate(cond.getExpression(), attrValue);
+            }
+        } catch (ValidationException e) {
+            LOG.error("Could not validate expression '" + cond.getExpression() + "'", e);
+            return EMPTY_ATTR_QUERY;
+        }
+
+        StringBuilder query = new StringBuilder("SELECT DISTINCT subject_id FROM ");
+        if (cond.getType() == AttributeCond.Type.ISNOTNULL) {
+            query.append(svs.field().name).
+                    append(" WHERE subject_id NOT IN (SELECT subject_id FROM ").
+                    append(svs.nullAttr().name).
+                    append(" WHERE schema_name='").append(schema.getKey()).append("')");
+        } else {
+            if (cond.getType() == AttributeCond.Type.ISNULL) {
+                query.append(svs.nullAttr().name).
+                        append(" WHERE schema_name='").append(schema.getKey()).append("'");
+            } else {
+                if (schema.isUniqueConstraint()) {
+                    query.append(svs.uniqueAttr().name);
+                } else {
+                    query.append(svs.attr().name);
+                }
+                query.append(" WHERE schema_name='").append(schema.getKey());
+
+                fillAttributeQuery(query, attrValue, schema, cond, not, parameters, svs);
+            }
+        }
+
+        return query.toString();
+    }
+
+    @SuppressWarnings("rawtypes")
+    private String getQuery(final SubjectCond cond, final boolean not, final List<Object> parameters,
+            final SubjectType type, final SearchSupport svs) {
+
+        final AttributableUtil attrUtil = JPAAttributableUtil.getInstance(type.asAttributableType());
+
+        Field subjectField = ReflectionUtils.findField(attrUtil.attributableClass(), cond.getSchema());
+        if (subjectField == null) {
+            LOG.warn("Ignoring invalid schema '{}'", cond.getSchema());
+            return EMPTY_ATTR_QUERY;
+        }
+
+        PlainSchema schema = attrUtil.newPlainSchema();
+        schema.setKey(subjectField.getName());
+        for (AttrSchemaType attrSchemaType : AttrSchemaType.values()) {
+            if (subjectField.getType().isAssignableFrom(attrSchemaType.getType())) {
+                schema.setType(attrSchemaType);
+            }
+        }
+
+        // Deal with subject Integer fields logically mapping to boolean values
+        // (SyncopeRole.inheritAttrs, for example)
+        boolean foundBooleanMin = false;
+        boolean foundBooleanMax = false;
+        if (Integer.class.equals(subjectField.getType())) {
+            for (Annotation annotation : subjectField.getAnnotations()) {
+                if (Min.class.equals(annotation.annotationType())) {
+                    foundBooleanMin = ((Min) annotation).value() == 0;
+                } else if (Max.class.equals(annotation.annotationType())) {
+                    foundBooleanMax = ((Max) annotation).value() == 1;
+                }
+            }
+        }
+        if (foundBooleanMin && foundBooleanMax) {
+            schema.setType(AttrSchemaType.Boolean);
+        }
+
+        // Deal with subject fields representing relationships to other entities
+        if (subjectField.getType().getAnnotation(Entity.class) != null) {
+            if (BeanUtils.findDeclaredMethodWithMinimalParameters(subjectField.getType(), "getId") != null) {
+                cond.setSchema(cond.getSchema() + "_id");
+                schema.setType(AttrSchemaType.Long);
+            }
+            if (BeanUtils.findDeclaredMethodWithMinimalParameters(subjectField.getType(), "getName") != null) {
+                cond.setSchema(cond.getSchema() + "_name");
+                schema.setType(AttrSchemaType.String);
+            }
+        }
+
+        PlainAttrValue attrValue = attrUtil.newPlainAttrValue();
+        if (cond.getType() != AttributeCond.Type.LIKE
+                && cond.getType() != AttributeCond.Type.ISNULL
+                && cond.getType() != AttributeCond.Type.ISNOTNULL) {
+
+            try {
+                schema.getValidator().validate(cond.getExpression(), attrValue);
+            } catch (ValidationException e) {
+                LOG.error("Could not validate expression '" + cond.getExpression() + "'", e);
+                return EMPTY_ATTR_QUERY;
+            }
+        }
+
+        final StringBuilder query = new StringBuilder("SELECT DISTINCT subject_id FROM ").
+                append(svs.field().name).append(" WHERE ");
+
+        fillAttributeQuery(query, attrValue, schema, cond, not, parameters, svs);
+
+        return query.toString();
+    }
+}


[07/32] syncope git commit: Updating antrun, failsafe and surefire plugins

Posted by il...@apache.org.
Updating antrun, failsafe and surefire plugins


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

Branch: refs/heads/2_0_X
Commit: f3a0871d1461efb1770514963dd6547dcc11b41e
Parents: 4229220
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Sun Dec 28 14:49:07 2014 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Sun Dec 28 14:49:07 2014 +0100

----------------------------------------------------------------------
 pom.xml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/f3a0871d/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 66dfa9e..ca77f16 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1070,7 +1070,7 @@ under the License.
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-surefire-plugin</artifactId>
-          <version>2.18</version>
+          <version>2.18.1</version>
           <configuration>
             <redirectTestOutputToFile>true</redirectTestOutputToFile>
             <encoding>utf-8</encoding>
@@ -1094,7 +1094,7 @@ under the License.
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-failsafe-plugin</artifactId>
-          <version>2.18</version>
+          <version>2.18.1</version>
           <configuration>
             <redirectTestOutputToFile>true</redirectTestOutputToFile>
             <encoding>utf-8</encoding>
@@ -1112,7 +1112,7 @@ under the License.
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-antrun-plugin</artifactId>
-          <version>1.7</version>
+          <version>1.8</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>


[16/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/resources/persistence.properties
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/resources/persistence.properties b/syncope620/server/persistence-jpa/src/test/resources/persistence.properties
new file mode 100644
index 0000000..3106b69
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/resources/persistence.properties
@@ -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.
+jpa.driverClassName=org.h2.Driver
+jpa.url=jdbc:h2:mem:syncopedb;DB_CLOSE_DELAY=-1
+jpa.username=sa
+jpa.password=
+jpa.dialect=org.apache.openjpa.jdbc.sql.H2Dictionary
+jpa.pool.validationQuery=SELECT 1
+#note: other connection pool settings can also be configured here, see persistenceContext.xml
+quartz.jobstore=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
+quartz.scheduler.idleWaitTime=5000
+quartz.sql=tables_h2.sql
+audit.sql=audit.sql
+database.schema=
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/resources/persistenceTestEnv.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/resources/persistenceTestEnv.xml b/syncope620/server/persistence-jpa/src/test/resources/persistenceTestEnv.xml
new file mode 100644
index 0000000..53bc496
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/resources/persistenceTestEnv.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+                           http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/context
+                           http://www.springframework.org/schema/context/spring-context.xsd">
+
+  <bean class="org.apache.syncope.server.spring.ApplicationContextProvider"/>
+
+  <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+    <property name="locations">
+      <list>
+        <value>classpath:security.properties</value>
+      </list>
+    </property>
+    <property name="ignoreResourceNotFound" value="true"/>
+    <property name="ignoreUnresolvablePlaceholders" value="true"/>
+  </bean>
+  <bean id="adminUser" class="java.lang.String">
+    <constructor-arg value="${adminUser}"/>
+  </bean>
+  <bean id="anonymousUser" class="java.lang.String">
+    <constructor-arg value="${anonymousUser}"/>
+  </bean>
+  
+  <context:component-scan base-package="org.apache.syncope.server.utils"/>
+
+  <import resource="persistenceContext.xml"/>
+</beans>

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/resources/simplelogger.properties
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/resources/simplelogger.properties b/syncope620/server/persistence-jpa/src/test/resources/simplelogger.properties
new file mode 100644
index 0000000..8abc668
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/resources/simplelogger.properties
@@ -0,0 +1,17 @@
+# 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.
+org.slf4j.simpleLogger.defaultLogLevel=error

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/pom.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/pom.xml b/syncope620/server/pom.xml
index b8c0503..fe6c089 100644
--- a/syncope620/server/pom.xml
+++ b/syncope620/server/pom.xml
@@ -34,8 +34,12 @@ under the License.
   <packaging>pom</packaging>
 
   <modules>
+    <module>provisioning-api</module>
     <module>persistence-api</module>
-    <!--<module>persistence-jpa</module>-->
+    <module>persistence-jpa</module>
+    <module>spring</module>
+    <module>security</module>
+    <module>utils</module>
   </modules>
 
 </project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/provisioning-api/pom.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-api/pom.xml b/syncope620/server/provisioning-api/pom.xml
new file mode 100644
index 0000000..aa27a1c
--- /dev/null
+++ b/syncope620/server/provisioning-api/pom.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.syncope</groupId>
+    <artifactId>syncope-server</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Server Provisioning API</name>
+  <description>Apache Syncope Server Provisioning API</description>
+  <groupId>org.apache.syncope.server</groupId>
+  <artifactId>syncope-provisioning-api</artifactId>
+  <packaging>jar</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>net.tirasa.connid</groupId>
+      <artifactId>connector-framework</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.quartz-scheduler</groupId>
+      <artifactId>quartz</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.syncope.server</groupId>
+      <artifactId>syncope-persistence-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/ConnPoolConfUtil.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/ConnPoolConfUtil.java b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/ConnPoolConfUtil.java
new file mode 100644
index 0000000..917473e
--- /dev/null
+++ b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/ConnPoolConfUtil.java
@@ -0,0 +1,69 @@
+/*
+ * 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.provisioning.api;
+
+import org.apache.syncope.common.lib.to.ConnPoolConfTO;
+import org.apache.syncope.persistence.api.entity.ConnPoolConf;
+import org.identityconnectors.common.pooling.ObjectPoolConfiguration;
+
+public final class ConnPoolConfUtil {
+
+    public static ConnPoolConf getConnPoolConf(final ConnPoolConfTO cpcto, final ConnPoolConf cpc) {
+        ObjectPoolConfiguration opc = new ObjectPoolConfiguration();
+
+        cpc.setMaxIdle(cpcto.getMaxIdle() == null ? opc.getMaxIdle() : cpcto.getMaxIdle());
+        cpc.setMaxObjects(cpcto.getMaxObjects() == null ? opc.getMaxObjects() : cpcto.getMaxObjects());
+        cpc.setMaxWait(cpcto.getMaxWait() == null ? opc.getMaxWait() : cpcto.getMaxWait());
+        cpc.setMinEvictableIdleTimeMillis(cpcto.getMinEvictableIdleTimeMillis() == null
+                ? opc.getMinEvictableIdleTimeMillis() : cpcto.getMinEvictableIdleTimeMillis());
+        cpc.setMinIdle(cpcto.getMinIdle() == null ? opc.getMinIdle() : cpcto.getMinIdle());
+
+        return cpc;
+    }
+
+    public static ObjectPoolConfiguration getObjectPoolConfiguration(final ConnPoolConf cpc) {
+        ObjectPoolConfiguration opc = new ObjectPoolConfiguration();
+        updateObjectPoolConfiguration(opc, cpc);
+        return opc;
+    }
+
+    public static void updateObjectPoolConfiguration(
+            final ObjectPoolConfiguration opc, final ConnPoolConf cpc) {
+
+        if (cpc.getMaxIdle() != null) {
+            opc.setMaxIdle(cpc.getMaxIdle());
+        }
+        if (cpc.getMaxObjects() != null) {
+            opc.setMaxObjects(cpc.getMaxObjects());
+        }
+        if (cpc.getMaxWait() != null) {
+            opc.setMaxWait(cpc.getMaxWait());
+        }
+        if (cpc.getMinEvictableIdleTimeMillis() != null) {
+            opc.setMinEvictableIdleTimeMillis(cpc.getMinEvictableIdleTimeMillis());
+        }
+        if (cpc.getMinIdle() != null) {
+            opc.setMinIdle(cpc.getMinIdle());
+        }
+    }
+
+    private ConnPoolConfUtil() {
+        // empty constructor for static utility class
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/Connector.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/Connector.java b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/Connector.java
new file mode 100644
index 0000000..de4b472
--- /dev/null
+++ b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/Connector.java
@@ -0,0 +1,216 @@
+/*
+ * 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.provisioning.api;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import org.apache.syncope.common.lib.types.PropagationMode;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.persistence.api.entity.ConnInstance;
+import org.apache.syncope.persistence.api.entity.MappingItem;
+import org.identityconnectors.framework.common.objects.Attribute;
+import org.identityconnectors.framework.common.objects.ConnectorObject;
+import org.identityconnectors.framework.common.objects.ObjectClass;
+import org.identityconnectors.framework.common.objects.OperationOptions;
+import org.identityconnectors.framework.common.objects.SyncResultsHandler;
+import org.identityconnectors.framework.common.objects.SyncToken;
+import org.identityconnectors.framework.common.objects.Uid;
+import org.identityconnectors.framework.common.objects.filter.Filter;
+
+/**
+ * Entry point for making requests on underlying connector bundles.
+ */
+public interface Connector {
+
+    /**
+     * Authenticate user on a connector instance.
+     *
+     * @param username the name based credential for authentication
+     * @param password the password based credential for authentication
+     * @param options ConnId's OperationOptions
+     * @return Uid of the account that was used to authenticate
+     */
+    Uid authenticate(String username, String password, OperationOptions options);
+
+    /**
+     * Create user / role on a connector instance.
+     *
+     * @param propagationMode propagation mode
+     * @param objectClass ConnId's object class
+     * @param attrs attributes for creation
+     * @param options ConnId's OperationOptions
+     * @param propagationAttempted if creation is actually performed (based on connector instance's capabilities)
+     * @return Uid for created object
+     */
+    Uid create(PropagationMode propagationMode, ObjectClass objectClass,
+            Set<Attribute> attrs, OperationOptions options,
+            Set<String> propagationAttempted);
+
+    /**
+     * Update user / role on a connector instance.
+     *
+     * @param propagationMode propagation mode
+     * @param objectClass ConnId's object class
+     * @param uid user to be updated
+     * @param attrs attributes for update
+     * @param options ConnId's OperationOptions
+     * @param propagationAttempted if update is actually performed (based on connector instance's capabilities)
+     * @return Uid for updated object
+     */
+    Uid update(PropagationMode propagationMode, ObjectClass objectClass,
+            Uid uid, Set<Attribute> attrs, OperationOptions options,
+            Set<String> propagationAttempted);
+
+    /**
+     * Delete user / role on a connector instance.
+     *
+     * @param propagationMode propagation mode
+     * @param objectClass ConnId's object class
+     * @param uid user to be deleted
+     * @param options ConnId's OperationOptions
+     * @param propagationAttempted if deletion is actually performed (based on connector instance's capabilities)
+     */
+    void delete(PropagationMode propagationMode, ObjectClass objectClass,
+            Uid uid, OperationOptions options, Set<String> propagationAttempted);
+
+    /**
+     * Sync users / roles from a connector instance.
+     *
+     * @param objectClass ConnId's object class
+     * @param token to be passed to the underlying connector
+     * @param handler to be used to handle deltas
+     * @param options ConnId's OperationOptions
+     */
+    void sync(ObjectClass objectClass, SyncToken token, SyncResultsHandler handler, OperationOptions options);
+
+    /**
+     * Read latest sync token from a connector instance.
+     *
+     * @param objectClass ConnId's object class.
+     * @return latest sync token
+     */
+    SyncToken getLatestSyncToken(ObjectClass objectClass);
+
+    /**
+     * Get remote object.
+     *
+     * @param objectClass ConnId's object class
+     * @param uid ConnId's Uid
+     * @param options ConnId's OperationOptions
+     * @return ConnId's connector object for given uid
+     */
+    ConnectorObject getObject(ObjectClass objectClass, Uid uid, OperationOptions options);
+
+    /**
+     * Get remote object used by the propagation manager in order to choose for a create (object doesn't exist) or an
+     * update (object exists).
+     *
+     * @param propagationMode propagation mode
+     * @param operationType resource operation type
+     * @param objectClass ConnId's object class
+     * @param uid ConnId's Uid
+     * @param options ConnId's OperationOptions
+     * @return ConnId's connector object for given uid
+     */
+    ConnectorObject getObject(PropagationMode propagationMode, ResourceOperation operationType, ObjectClass objectClass,
+            Uid uid, OperationOptions options);
+
+    /**
+     * Search for remote objects.
+     *
+     * @param objectClass ConnId's object class
+     * @param filter search filter
+     * @param options ConnId's OperationOptions
+     * @return ConnId's connector objects matching the given filter
+     */
+    List<ConnectorObject> search(ObjectClass objectClass, Filter filter, OperationOptions options);
+
+    /**
+     * Get remote object used by the propagation manager in order to choose for a create (object doesn't exist) or an
+     * update (object exists).
+     *
+     * @param objectClass ConnId's object class.
+     * @param handler to be used to handle deltas.
+     * @param options ConnId's OperationOptions.
+     */
+    void getAllObjects(ObjectClass objectClass, SyncResultsHandler handler, OperationOptions options);
+
+    /**
+     * Read attribute for a given connector object.
+     *
+     * @param objectClass ConnId's object class
+     * @param uid ConnId's Uid
+     * @param options ConnId's OperationOptions
+     * @param attributeName attribute to read
+     * @return attribute (if present)
+     */
+    Attribute getObjectAttribute(ObjectClass objectClass, Uid uid, OperationOptions options, String attributeName);
+
+    /**
+     * Read attributes for a given connector object.
+     *
+     * @param objectClass ConnId's object class
+     * @param uid ConnId's Uid
+     * @param options ConnId's OperationOptions
+     * @return attributes (if present)
+     */
+    Set<Attribute> getObjectAttributes(ObjectClass objectClass, Uid uid, OperationOptions options);
+
+    /**
+     * Return resource schema names.
+     *
+     * @param includeSpecial return special attributes (like as __NAME__ or __PASSWORD__) if true
+     * @return schema names
+     */
+    Set<String> getSchemaNames(boolean includeSpecial);
+
+    /**
+     * Return ConnId's object classes supported by this connector.
+     *
+     * @return supported object classes
+     */
+    Set<ObjectClass> getSupportedObjectClasses();
+
+    /**
+     * Validate a connector instance.
+     */
+    void validate();
+
+    /**
+     * Check connection to resource.
+     */
+    void test();
+
+    /**
+     * Getter for active connector instance.
+     *
+     * @return active connector instance.
+     */
+    ConnInstance getActiveConnInstance();
+
+    /**
+     * Build options for requesting all mapped connector attributes.
+     *
+     * @param mapItems mapping items
+     * @return options for requesting all mapped connector attributes
+     * @see OperationOptions
+     */
+    OperationOptions getOperationOptions(Collection<MappingItem> mapItems);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/ConnectorFactory.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/ConnectorFactory.java b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/ConnectorFactory.java
new file mode 100644
index 0000000..e68975c
--- /dev/null
+++ b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/ConnectorFactory.java
@@ -0,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.provisioning.api;
+
+import java.util.Set;
+import org.apache.syncope.common.lib.types.ConnConfProperty;
+import org.apache.syncope.persistence.api.entity.ConnInstance;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+
+/**
+ * Entry point for creating and destroying connectors for external resources.
+ *
+ * @see org.apache.syncope.core.propagation.Connector
+ */
+public interface ConnectorFactory {
+
+    /**
+     * Create connector from given connector instance and configuration properties.
+     *
+     * @param connInstance connector instance
+     * @param configuration configuration properties
+     * @return connector
+     */
+    Connector createConnector(ConnInstance connInstance, Set<ConnConfProperty> configuration);
+
+    /**
+     * Get existing connector for the given resource.
+     *
+     * @param resource the resource.
+     * @return live connector bran for given resource
+     */
+    Connector getConnector(ExternalResource resource);
+
+    /**
+     * Load connectors for all existing resources.
+     *
+     * @see ExternalResource
+     */
+    void load();
+
+    /**
+     * Unload connectors for all existing resources.
+     *
+     * @see ExternalResource
+     */
+    void unload();
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/ConnectorRegistry.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/ConnectorRegistry.java b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/ConnectorRegistry.java
new file mode 100644
index 0000000..aa1d1c0
--- /dev/null
+++ b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/ConnectorRegistry.java
@@ -0,0 +1,41 @@
+/*
+ * 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.provisioning.api;
+
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+
+/**
+ * Manage Spring beans lifecycle for connectors.
+ */
+public interface ConnectorRegistry {
+
+    /**
+     * Create and register into Spring context a bean for the given resource.
+     *
+     * @param resource external resource
+     */
+    void registerConnector(ExternalResource resource);
+
+    /**
+     * Removes the Spring bean for the given id from the context.
+     *
+     * @param id Spring bean id
+     */
+    void unregisterConnector(String id);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/job/ProvisioningJob.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/job/ProvisioningJob.java b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/job/ProvisioningJob.java
new file mode 100644
index 0000000..68e8dae
--- /dev/null
+++ b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/job/ProvisioningJob.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.provisioning.api.job;
+
+import java.util.List;
+import org.apache.syncope.persistence.api.entity.task.ProvisioningTask;
+import org.apache.syncope.provisioning.api.sync.ProvisioningActions;
+
+public interface ProvisioningJob<T extends ProvisioningTask, A extends ProvisioningActions> extends TaskJob {
+
+    void setActions(List<A> actions);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/job/PushJob.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/job/PushJob.java b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/job/PushJob.java
new file mode 100644
index 0000000..016623c
--- /dev/null
+++ b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/job/PushJob.java
@@ -0,0 +1,26 @@
+/*
+ * 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.provisioning.api.job;
+
+import org.apache.syncope.persistence.api.entity.task.PushTask;
+import org.apache.syncope.provisioning.api.sync.PushActions;
+
+public interface PushJob extends ProvisioningJob<PushTask, PushActions> {
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/job/SyncJob.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/job/SyncJob.java b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/job/SyncJob.java
new file mode 100644
index 0000000..fa74c8f
--- /dev/null
+++ b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/job/SyncJob.java
@@ -0,0 +1,26 @@
+/*
+ * 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.provisioning.api.job;
+
+import org.apache.syncope.persistence.api.entity.task.SyncTask;
+import org.apache.syncope.provisioning.api.sync.SyncActions;
+
+public interface SyncJob extends ProvisioningJob<SyncTask, SyncActions> {
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/job/TaskJob.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/job/TaskJob.java b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/job/TaskJob.java
new file mode 100644
index 0000000..94f906e
--- /dev/null
+++ b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/job/TaskJob.java
@@ -0,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.provisioning.api.job;
+
+import org.quartz.DisallowConcurrentExecution;
+import org.quartz.Job;
+
+/**
+ * Interface for Quartz jobs bound to a given Task.
+ */
+@DisallowConcurrentExecution
+public interface TaskJob extends Job {
+
+    public static final String DRY_RUN_JOBDETAIL_KEY = "dryRun";
+
+    /**
+     * Task execution status.
+     */
+    public enum Status {
+
+        SUCCESS,
+        FAILURE
+
+    }
+
+    void setTaskId(Long taskId);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/propagation/PropagationActions.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/propagation/PropagationActions.java b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/propagation/PropagationActions.java
new file mode 100644
index 0000000..d23843e
--- /dev/null
+++ b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/propagation/PropagationActions.java
@@ -0,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.provisioning.api.propagation;
+
+import org.apache.syncope.persistence.api.entity.task.PropagationTask;
+import org.apache.syncope.persistence.api.entity.task.TaskExec;
+import org.identityconnectors.framework.common.objects.ConnectorObject;
+
+public interface PropagationActions {
+
+    void before(PropagationTask task, ConnectorObject beforeObj);
+
+    void after(PropagationTask task, TaskExec execution, ConnectorObject afterObj);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/ProvisioningActions.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/ProvisioningActions.java b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/ProvisioningActions.java
new file mode 100644
index 0000000..f69a455
--- /dev/null
+++ b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/ProvisioningActions.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.provisioning.api.sync;
+
+import java.util.List;
+import org.quartz.JobExecutionException;
+
+public interface ProvisioningActions {
+
+    /**
+     * Action to be executed before to start the synchronization task execution.
+     *
+     * @param profile sync profile
+     * @throws JobExecutionException in case of generic failure
+     */
+    void beforeAll(final SyncProfile<?, ?> profile) throws JobExecutionException;
+
+    /**
+     * Action to be executed after the synchronization task completion.
+     *
+     * @param profile sync profile
+     * @param results synchronization result
+     * @throws JobExecutionException in case of generic failure
+     */
+    void afterAll(final SyncProfile<?, ?> profile, final List<SyncResult> results) throws JobExecutionException;
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/PushActions.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/PushActions.java b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/PushActions.java
new file mode 100644
index 0000000..fc79334
--- /dev/null
+++ b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/PushActions.java
@@ -0,0 +1,137 @@
+/*
+ * 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.provisioning.api.sync;
+
+import org.apache.syncope.persistence.api.entity.Subject;
+import org.quartz.JobExecutionException;
+
+/**
+ * Interface for actions to be performed during PushJob execution.
+ */
+public interface PushActions extends ProvisioningActions {
+
+    /**
+     * Action to be executed before to assign (link & provision) a synchronized user / role to the resource.
+     *
+     * @param profile profile of the synchronization being executed.
+     * @param subject user / role to be created.
+     * @return subject.
+     * @throws JobExecutionException in case of generic failure
+     */
+    <T extends Subject<?, ?, ?>> T beforeAssign(
+            final SyncProfile<?, ?> profile,
+            final T subject) throws JobExecutionException;
+
+    /**
+     * Action to be executed before to provision a synchronized user / role to the resource.
+     *
+     * @param profile profile of the synchronization being executed.
+     * @param subject user / role to be created.
+     * @return subject.
+     * @throws JobExecutionException in case of generic failure
+     */
+    <T extends Subject<?, ?, ?>> T beforeProvision(
+            final SyncProfile<?, ?> profile,
+            final T subject) throws JobExecutionException;
+
+    /**
+     * Action to be executed before to update a synchronized user / role on the resource.
+     *
+     * @param profile profile of the synchronization being executed.
+     * @param subject user / role to be updated.
+     * @return subject.
+     * @throws JobExecutionException in case of generic failure
+     */
+    <T extends Subject<?, ?, ?>> T beforeUpdate(
+            final SyncProfile<?, ?> profile,
+            final T subject) throws JobExecutionException;
+
+    /**
+     * Action to be executed before to link a synchronized user / role to the resource.
+     *
+     * @param profile profile of the synchronization being executed.
+     * @param subject user / role to be created.
+     * @return subject.
+     * @throws JobExecutionException in case of generic failure
+     */
+    <T extends Subject<?, ?, ?>> T beforeLink(
+            final SyncProfile<?, ?> profile,
+            final T subject) throws JobExecutionException;
+
+    /**
+     * Action to be executed before to unlink a synchronized user / role from the resource.
+     *
+     * @param profile profile of the synchronization being executed.
+     * @param subject user / role to be created.
+     * @return subject.
+     * @throws JobExecutionException in case of generic failure
+     */
+    <T extends Subject<?, ?, ?>> T beforeUnlink(
+            final SyncProfile<?, ?> profile,
+            final T subject) throws JobExecutionException;
+
+    /**
+     * Action to be executed before to unassign a synchronized user / role from the resource.
+     *
+     * @param profile profile of the synchronization being executed.
+     * @param subject user / role to be created.
+     * @return subject.
+     * @throws JobExecutionException in case of generic failure
+     */
+    <T extends Subject<?, ?, ?>> T beforeUnassign(
+            final SyncProfile<?, ?> profile,
+            final T subject) throws JobExecutionException;
+
+    /**
+     * Action to be executed before to unassign a synchronized user / role from the resource.
+     *
+     * @param profile profile of the synchronization being executed.
+     * @param subject user / role to be created.
+     * @return subject.
+     * @throws JobExecutionException in case of generic failure
+     */
+    <T extends Subject<?, ?, ?>> T beforeDeprovision(
+            final SyncProfile<?, ?> profile,
+            final T subject) throws JobExecutionException;
+
+    /**
+     * Action to be executed before delete a synchronized user / role locally and from the resource.
+     *
+     * @param profile profile of the synchronization being executed.
+     * @param subject user / role to be created.
+     * @return subject.
+     * @throws JobExecutionException in case of generic failure
+     */
+    <T extends Subject<?, ?, ?>> T beforeDelete(
+            final SyncProfile<?, ?> profile,
+            final T subject) throws JobExecutionException;
+
+    /**
+     * Action to be executed after each local user / role synchronization.
+     *
+     * @param profile profile of the synchronization being executed.
+     * @param subject synchronized user / role.
+     * @param result operation result.
+     * @throws JobExecutionException in case of generic failure
+     */
+    <T extends Subject<?, ?, ?>> void after(
+            final SyncProfile<?, ?> profile,
+            final T subject,
+            final SyncResult result) throws JobExecutionException;
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/SyncActions.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/SyncActions.java b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/SyncActions.java
new file mode 100644
index 0000000..ae6c3b3
--- /dev/null
+++ b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/SyncActions.java
@@ -0,0 +1,175 @@
+/*
+ * 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.provisioning.api.sync;
+
+import org.apache.syncope.common.lib.mod.AbstractSubjectMod;
+import org.apache.syncope.common.lib.to.AbstractSubjectTO;
+import org.identityconnectors.framework.common.objects.SyncDelta;
+import org.quartz.JobExecutionException;
+
+/**
+ * Interface for actions to be performed during SyncJob execution.
+ */
+public interface SyncActions extends ProvisioningActions {
+
+    /**
+     * Action to be executed before to create a synchronized user / role locally.
+     * User/role is created locally upon synchronization in case of the un-matching rule
+     * {@link org.apache.syncope.common.types.UnmatchingRule#PROVISION} (default un-matching rule) is applied.
+     *
+     * @param profile profile of the synchronization being executed.
+     * @param delta retrieved synchronization information
+     * @param subject user / role to be created
+     * @return synchronization information used for user status evaluation and to be passed to the 'after' method.
+     * @throws JobExecutionException in case of generic failure
+     */
+    <T extends AbstractSubjectTO> SyncDelta beforeProvision(
+            final SyncProfile<?, ?> profile,
+            final SyncDelta delta,
+            final T subject) throws JobExecutionException;
+
+    /**
+     * Action to be executed before creating (and linking to the resource) a synchronized user / role locally.
+     * User/role is created locally and linked to the synchronized resource upon synchronization in case of the
+     * un-matching rule {@link org.apache.syncope.common.types.UnmatchingRule#ASSIGN} is applied.
+     *
+     * @param profile profile of the synchronization being executed.
+     * @param delta retrieved synchronization information
+     * @param subject user / role to be created
+     * @return synchronization information used for user status evaluation and to be passed to the 'after' method.
+     * @throws JobExecutionException in case of generic failure
+     */
+    <T extends AbstractSubjectTO> SyncDelta beforeAssign(
+            final SyncProfile<?, ?> profile,
+            final SyncDelta delta,
+            final T subject) throws JobExecutionException;
+
+    /**
+     * Action to be executed before unlinking resource from the synchronized user / role and de-provisioning.
+     * User/role is unlinked and de-provisioned from the synchronized resource upon synchronization in case of the
+     * matching rule {@link org.apache.syncope.common.types.MatchingRule#UNASSIGN} is applied.
+     *
+     * @param profile profile of the synchronization being executed.
+     * @param delta retrieved synchronization information
+     * @param subject user / role to be created
+     * @return synchronization information used for user status evaluation and to be passed to the 'after' method.
+     * @throws JobExecutionException in case of generic failure
+     */
+    <T extends AbstractSubjectTO> SyncDelta beforeUnassign(
+            final SyncProfile<?, ?> profile,
+            final SyncDelta delta,
+            final T subject) throws JobExecutionException;
+
+    /**
+     * Action to be executed before de-provisioning action only.
+     * User/role is de-provisioned (without unlinking) from the synchronized resource upon synchronization in case of
+     * the matching rule {@link org.apache.syncope.common.types.MatchingRule#DEPROVISION} is applied.
+     *
+     * @param profile profile of the synchronization being executed.
+     * @param delta retrieved synchronization information
+     * @param subject user / role to be created
+     * @return synchronization information used for user status evaluation and to be passed to the 'after' method.
+     * @throws JobExecutionException in case of generic failure
+     */
+    <T extends AbstractSubjectTO> SyncDelta beforeDeprovision(
+            final SyncProfile<?, ?> profile,
+            final SyncDelta delta,
+            final T subject) throws JobExecutionException;
+
+    /**
+     * Action to be executed before unlinking resource from the synchronized user / role.
+     * User/role is unlinked (without de-provisioning) from the synchronized resource upon synchronization in case of
+     * the matching rule {@link org.apache.syncope.common.types.MatchingRule#UNLINK} is applied.
+     *
+     * @param profile profile of the synchronization being executed.
+     * @param delta retrieved synchronization information
+     * @param subject user / role to be created
+     * @return synchronization information used for user status evaluation and to be passed to the 'after' method.
+     * @throws JobExecutionException in case of generic failure
+     */
+    <T extends AbstractSubjectTO> SyncDelta beforeUnlink(
+            final SyncProfile<?, ?> profile,
+            final SyncDelta delta,
+            final T subject) throws JobExecutionException;
+
+    /**
+     * Action to be executed before linking resource to the synchronized user / role.
+     * User/role is linked (without updating) to the synchronized resource upon synchronization in case of
+     * the matching rule {@link org.apache.syncope.common.types.MatchingRule#LINK} is applied.
+     *
+     * @param profile profile of the synchronization being executed.
+     * @param delta retrieved synchronization information
+     * @param subject user / role to be created
+     * @return synchronization information used for user status evaluation and to be passed to the 'after' method.
+     * @throws JobExecutionException in case of generic failure
+     */
+    <T extends AbstractSubjectTO> SyncDelta beforeLink(
+            final SyncProfile<?, ?> profile,
+            final SyncDelta delta,
+            final T subject) throws JobExecutionException;
+
+    /**
+     * Action to be executed before to update a synchronized user / role locally.
+     * User/role is updated upon synchronization in case of the matching rule
+     * {@link org.apache.syncope.common.types.MatchingRule#UPDATE} (default matching rule) is applied.
+     *
+     * @param profile profile of the synchronization being executed.
+     * @param delta retrieved synchronization information
+     * @param subject local user / role information
+     * @param subjectMod modification
+     * @return synchronization information used for logging and to be passed to the 'after' method.
+     * @throws JobExecutionException in case of generic failure.
+     */
+    <T extends AbstractSubjectTO, K extends AbstractSubjectMod> SyncDelta beforeUpdate(
+            final SyncProfile<?, ?> profile,
+            final SyncDelta delta,
+            final T subject,
+            final K subjectMod)
+            throws JobExecutionException;
+
+    /**
+     * Action to be executed before to delete a synchronized user / role locally.
+     *
+     * @param profile profile of the synchronization being executed.
+     * @param delta retrieved synchronization information
+     * @param subject local user / role to be deleted
+     * @return synchronization information used for logging and to be passed to the 'after' method.
+     * @throws JobExecutionException in case of generic failure
+     */
+    <T extends AbstractSubjectTO> SyncDelta beforeDelete(
+            final SyncProfile<?, ?> profile,
+            final SyncDelta delta,
+            final T subject) throws JobExecutionException;
+
+    /**
+     * Action to be executed after each local user / role synchronization.
+     *
+     * @param profile profile of the synchronization being executed.
+     * @param delta retrieved synchronization information (may be modified by
+     * 'beforeProvision/beforeUpdate/beforeDelete')
+     * @param subject synchronized local user / role
+     * @param result global synchronization results at the current synchronization step
+     * @throws JobExecutionException in case of generic failure
+     */
+    <T extends AbstractSubjectTO> void after(
+            final SyncProfile<?, ?> profile,
+            final SyncDelta delta,
+            final T subject,
+            final SyncResult result) throws JobExecutionException;
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/SyncProfile.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/SyncProfile.java b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/SyncProfile.java
new file mode 100644
index 0000000..77cbfe1
--- /dev/null
+++ b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/SyncProfile.java
@@ -0,0 +1,84 @@
+/*
+ * 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.provisioning.api.sync;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.syncope.common.lib.types.ConflictResolutionAction;
+import org.apache.syncope.persistence.api.entity.task.SyncTask;
+import org.apache.syncope.provisioning.api.Connector;
+
+public class SyncProfile<T extends SyncTask, A extends ProvisioningActions> {
+
+    /**
+     * Syncing connector.
+     */
+    private final Connector connector;
+
+    private final T syncTask;
+
+    private Collection<SyncResult> results;
+
+    private boolean dryRun;
+
+    private ConflictResolutionAction resAct;
+
+    private List<A> actions;
+
+    public SyncProfile(final Connector connector, final T syncTask) {
+        this.connector = connector;
+        this.syncTask = syncTask;
+    }
+
+    public Connector getConnector() {
+        return connector;
+    }
+
+    public T getSyncTask() {
+        return syncTask;
+    }
+
+    public Collection<SyncResult> getResults() {
+        return results;
+    }
+
+    public boolean isDryRun() {
+        return dryRun;
+    }
+
+    public void setDryRun(final boolean dryRun) {
+        this.dryRun = dryRun;
+    }
+
+    public ConflictResolutionAction getResAct() {
+        return resAct;
+    }
+
+    public void setResAct(final ConflictResolutionAction resAct) {
+        this.resAct = resAct;
+    }
+
+    public List<A> getActions() {
+        return actions;
+    }
+
+    public void setActions(final List<A> actions) {
+        this.actions = actions;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/SyncResult.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/SyncResult.java b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/SyncResult.java
new file mode 100644
index 0000000..e6c17ea
--- /dev/null
+++ b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/SyncResult.java
@@ -0,0 +1,140 @@
+/*
+ * 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.provisioning.api.sync;
+
+import java.util.Collection;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.common.lib.types.TraceLevel;
+
+public class SyncResult {
+
+    public enum Status {
+
+        SUCCESS,
+        FAILURE
+
+    }
+
+    private String message;
+
+    private Status status;
+
+    private AttributableType subjectType;
+
+    private ResourceOperation operation;
+
+    private Long id;
+
+    private String name;
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(final String message) {
+        this.message = message;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(final Long id) {
+        this.id = id;
+    }
+
+    public Status getStatus() {
+        return status;
+    }
+
+    public void setStatus(final Status status) {
+        this.status = status;
+    }
+
+    public AttributableType getSubjectType() {
+        return subjectType;
+    }
+
+    public void setSubjectType(final AttributableType subjectType) {
+        this.subjectType = subjectType;
+    }
+
+    public ResourceOperation getOperation() {
+        return operation;
+    }
+
+    public void setOperation(final ResourceOperation operation) {
+        this.operation = operation;
+    }
+
+    @Override
+    public String toString() {
+        return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString();
+    }
+
+    /**
+     * Human readable report string, using the given trace level.
+     *
+     * @param level trace level
+     * @return String for certain levels, null for level NONE
+     */
+    public String getReportString(final TraceLevel level) {
+        if (level == TraceLevel.SUMMARY) {
+            // No per entry log in this case.
+            return null;
+        } else if (level == TraceLevel.FAILURES && status == Status.FAILURE) {
+            // only report failures
+            return String.format("Failed %s (id/name): %d/%s with message: %s", operation, id, name, message);
+        } else {
+            // All
+            return String.format("%s %s (id/name): %d/%s %s", operation, status, id, name,
+                    StringUtils.isBlank(message)
+                            ? ""
+                            : "with message: " + message);
+        }
+    }
+
+    /**
+     * Helper method to invoke logging per synchronization result for the given trace level.
+     *
+     * @param results synchronization result
+     * @param level trace level
+     * @return report as string
+     */
+    public static String produceReport(final Collection<SyncResult> results, final TraceLevel level) {
+        StringBuilder sb = new StringBuilder();
+        for (SyncResult result : results) {
+            sb.append(result.getReportString(level)).append("\n");
+        }
+        return sb.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/SyncopeResultHandler.java
----------------------------------------------------------------------
diff --git a/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/SyncopeResultHandler.java b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/SyncopeResultHandler.java
new file mode 100644
index 0000000..b3b366c
--- /dev/null
+++ b/syncope620/server/provisioning-api/src/main/java/org/apache/syncope/provisioning/api/sync/SyncopeResultHandler.java
@@ -0,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.provisioning.api.sync;
+
+import org.apache.syncope.persistence.api.entity.task.SyncTask;
+
+public interface SyncopeResultHandler<T extends SyncTask, A extends SyncActions> {
+
+    SyncProfile<T, A> getProfile();
+
+    void setProfilee(SyncProfile<T, A> profile);
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/security/pom.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/security/pom.xml b/syncope620/server/security/pom.xml
new file mode 100644
index 0000000..255f04d
--- /dev/null
+++ b/syncope620/server/security/pom.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.syncope</groupId>
+    <artifactId>syncope-server</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Server Security Features</name>
+  <description>Apache Syncope Server Security Features</description>
+  <groupId>org.apache.syncope.server</groupId>
+  <artifactId>syncope-server-security</artifactId>
+  <packaging>jar</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.jasypt</groupId>
+      <artifactId>jasypt</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.security</groupId>
+      <artifactId>spring-security-core</artifactId>
+    </dependency>
+      
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.syncope.common</groupId>
+      <artifactId>syncope-common-lib</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+        <filtering>true</filtering>
+      </resource>
+    </resources>
+  </build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/security/src/main/java/org/apache/syncope/server/security/AuthContextUtil.java
----------------------------------------------------------------------
diff --git a/syncope620/server/security/src/main/java/org/apache/syncope/server/security/AuthContextUtil.java b/syncope620/server/security/src/main/java/org/apache/syncope/server/security/AuthContextUtil.java
new file mode 100644
index 0000000..f414a37
--- /dev/null
+++ b/syncope620/server/security/src/main/java/org/apache/syncope/server/security/AuthContextUtil.java
@@ -0,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.server.security;
+
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+public final class AuthContextUtil {
+
+    public static String getAuthenticatedUsername() {
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+        return authentication == null ? SyncopeConstants.UNAUTHENTICATED : authentication.getName();
+    }
+
+    public static Set<String> getOwnedEntitlementNames() {
+        final Set<String> result = new HashSet<String>();
+
+        final SecurityContext ctx = SecurityContextHolder.getContext();
+
+        if (ctx != null && ctx.getAuthentication() != null && ctx.getAuthentication().getAuthorities() != null) {
+            for (GrantedAuthority authority : ctx.getAuthentication().getAuthorities()) {
+                result.add(authority.getAuthority());
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Private default constructor, for static-only classes.
+     */
+    private AuthContextUtil() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/security/src/main/java/org/apache/syncope/server/security/Encryptor.java
----------------------------------------------------------------------
diff --git a/syncope620/server/security/src/main/java/org/apache/syncope/server/security/Encryptor.java b/syncope620/server/security/src/main/java/org/apache/syncope/server/security/Encryptor.java
new file mode 100644
index 0000000..7cb0a0c
--- /dev/null
+++ b/syncope620/server/security/src/main/java/org/apache/syncope/server/security/Encryptor.java
@@ -0,0 +1,256 @@
+/*
+ * 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.server.security;
+
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.SecretKeySpec;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.types.CipherAlgorithm;
+import org.jasypt.commons.CommonUtils;
+import org.jasypt.digest.StandardStringDigester;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.crypto.bcrypt.BCrypt;
+import org.springframework.security.crypto.codec.Base64;
+
+public final class Encryptor {
+
+    private static final Logger LOG = LoggerFactory.getLogger(Encryptor.class);
+
+    private static final Map<String, Encryptor> INSTANCES = new ConcurrentHashMap<String, Encryptor>();
+
+    private static final String DEFAULT_SECRET_KEY = "1abcdefghilmnopqrstuvz2!";
+
+    /**
+     * Default value for salted {@link StandardStringDigester#setIterations(int)}.
+     */
+    private static final int DEFAULT_SALT_ITERATIONS = 1;
+
+    /**
+     * Default value for {@link StandardStringDigester#setSaltSizeBytes(int)}.
+     */
+    private static final int DEFAULT_SALT_SIZE_BYTES = 8;
+
+    /**
+     * Default value for {@link StandardStringDigester#setInvertPositionOfPlainSaltInEncryptionResults(boolean)}.
+     */
+    private static final boolean DEFAULT_IPOPSIER = true;
+
+    /**
+     * Default value for salted {@link StandardStringDigester#setInvertPositionOfSaltInMessageBeforeDigesting(boolean)}.
+     */
+    private static final boolean DEFAULT_IPOSIMBD = true;
+
+    /**
+     * Default value for salted {@link StandardStringDigester#setUseLenientSaltSizeCheck(boolean)}.
+     */
+    private static final boolean DEFAULT_ULSSC = true;
+
+    private static String secretKey;
+
+    private static Integer saltIterations;
+
+    private static Integer saltSizeBytes;
+
+    private static Boolean ipopsier;
+
+    private static Boolean iposimbd;
+
+    private static Boolean ulssc;
+
+    static {
+        InputStream propStream = null;
+        try {
+            propStream = Encryptor.class.getResourceAsStream("/security.properties");
+            Properties props = new Properties();
+            props.load(propStream);
+
+            secretKey = props.getProperty("secretKey");
+            saltIterations = Integer.valueOf(props.getProperty("digester.saltIterations"));
+            saltSizeBytes = Integer.valueOf(props.getProperty("digester.saltSizeBytes"));
+            ipopsier = Boolean.valueOf(props.getProperty("digester.invertPositionOfPlainSaltInEncryptionResults"));
+            iposimbd = Boolean.valueOf(props.getProperty("digester.invertPositionOfSaltInMessageBeforeDigesting"));
+            ulssc = Boolean.valueOf(props.getProperty("digester.useLenientSaltSizeCheck"));
+        } catch (Exception e) {
+            LOG.error("Could not read security parameters", e);
+        } finally {
+            IOUtils.closeQuietly(propStream);
+        }
+
+        if (secretKey == null) {
+            secretKey = DEFAULT_SECRET_KEY;
+            LOG.debug("secretKey not found, reverting to default");
+        }
+        if (saltIterations == null) {
+            saltIterations = DEFAULT_SALT_ITERATIONS;
+            LOG.debug("digester.saltIterations not found, reverting to default");
+        }
+        if (saltSizeBytes == null) {
+            saltSizeBytes = DEFAULT_SALT_SIZE_BYTES;
+            LOG.debug("digester.saltSizeBytes not found, reverting to default");
+        }
+        if (ipopsier == null) {
+            ipopsier = DEFAULT_IPOPSIER;
+            LOG.debug("digester.invertPositionOfPlainSaltInEncryptionResults not found, reverting to default");
+        }
+        if (iposimbd == null) {
+            iposimbd = DEFAULT_IPOSIMBD;
+            LOG.debug("digester.invertPositionOfSaltInMessageBeforeDigesting not found, reverting to default");
+        }
+        if (ulssc == null) {
+            ulssc = DEFAULT_ULSSC;
+            LOG.debug("digester.useLenientSaltSizeCheck not found, reverting to default");
+        }
+    }
+
+    public static Encryptor getInstance() {
+        return getInstance(secretKey);
+    }
+
+    public static Encryptor getInstance(final String secretKey) {
+        String actualKey = StringUtils.isBlank(secretKey) ? DEFAULT_SECRET_KEY : secretKey;
+
+        Encryptor instance = INSTANCES.get(actualKey);
+        if (instance == null) {
+            instance = new Encryptor(actualKey);
+            INSTANCES.put(actualKey, instance);
+        }
+
+        return instance;
+    }
+
+    private SecretKeySpec keySpec;
+
+    private Encryptor(final String secretKey) {
+        String actualKey = secretKey;
+        if (actualKey.length() < 16) {
+            StringBuilder actualKeyPadding = new StringBuilder(actualKey);
+            for (int i = 0; i < 16 - actualKey.length(); i++) {
+                actualKeyPadding.append('0');
+            }
+            actualKey = actualKeyPadding.toString();
+            LOG.debug("actualKey too short, adding some random characters");
+        }
+
+        try {
+            keySpec = new SecretKeySpec(ArrayUtils.subarray(
+                    actualKey.getBytes(SyncopeConstants.DEFAULT_ENCODING), 0, 16),
+                    CipherAlgorithm.AES.getAlgorithm());
+        } catch (Exception e) {
+            LOG.error("Error during key specification", e);
+        }
+    }
+
+    public String encode(final String value, final CipherAlgorithm cipherAlgorithm)
+            throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
+            IllegalBlockSizeException, BadPaddingException {
+
+        String encodedValue = null;
+
+        if (value != null) {
+            if (cipherAlgorithm == null || cipherAlgorithm == CipherAlgorithm.AES) {
+                final byte[] cleartext = value.getBytes(SyncopeConstants.DEFAULT_ENCODING);
+
+                final Cipher cipher = Cipher.getInstance(CipherAlgorithm.AES.getAlgorithm());
+                cipher.init(Cipher.ENCRYPT_MODE, keySpec);
+
+                encodedValue = new String(Base64.encode(cipher.doFinal(cleartext)));
+            } else if (cipherAlgorithm == CipherAlgorithm.BCRYPT) {
+                encodedValue = BCrypt.hashpw(value, BCrypt.gensalt());
+            } else {
+                encodedValue = getDigester(cipherAlgorithm).digest(value);
+            }
+        }
+
+        return encodedValue;
+    }
+
+    public boolean verify(final String value, final CipherAlgorithm cipherAlgorithm, final String encodedValue) {
+        boolean res = false;
+
+        try {
+            if (value != null) {
+                if (cipherAlgorithm == null || cipherAlgorithm == CipherAlgorithm.AES) {
+                    res = encode(value, cipherAlgorithm).equals(encodedValue);
+                } else if (cipherAlgorithm == CipherAlgorithm.BCRYPT) {
+                    res = BCrypt.checkpw(value, encodedValue);
+                } else {
+                    res = getDigester(cipherAlgorithm).matches(value, encodedValue);
+                }
+            }
+        } catch (Exception e) {
+            LOG.error("Could not verify encoded value", e);
+        }
+
+        return res;
+    }
+
+    public String decode(final String encodedValue, final CipherAlgorithm cipherAlgorithm)
+            throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
+            IllegalBlockSizeException, BadPaddingException {
+
+        String value = null;
+
+        if (encodedValue != null && cipherAlgorithm == CipherAlgorithm.AES) {
+            final byte[] encoded = encodedValue.getBytes(SyncopeConstants.DEFAULT_ENCODING);
+
+            final Cipher cipher = Cipher.getInstance(CipherAlgorithm.AES.getAlgorithm());
+            cipher.init(Cipher.DECRYPT_MODE, keySpec);
+
+            value = new String(cipher.doFinal(Base64.decode(encoded)), SyncopeConstants.DEFAULT_ENCODING);
+        }
+
+        return value;
+    }
+
+    private StandardStringDigester getDigester(final CipherAlgorithm cipherAlgorithm) {
+        StandardStringDigester digester = new StandardStringDigester();
+
+        if (cipherAlgorithm.getAlgorithm().startsWith("S-")) {
+            // Salted ...
+            digester.setAlgorithm(cipherAlgorithm.getAlgorithm().replaceFirst("S\\-", ""));
+            digester.setIterations(saltIterations);
+            digester.setSaltSizeBytes(saltSizeBytes);
+            digester.setInvertPositionOfPlainSaltInEncryptionResults(ipopsier);
+            digester.setInvertPositionOfSaltInMessageBeforeDigesting(iposimbd);
+            digester.setUseLenientSaltSizeCheck(ulssc);
+        } else {
+            // Not salted ...
+            digester.setAlgorithm(cipherAlgorithm.getAlgorithm());
+            digester.setIterations(1);
+            digester.setSaltSizeBytes(0);
+        }
+
+        digester.setStringOutputType(CommonUtils.STRING_OUTPUT_TYPE_HEXADECIMAL);
+        return digester;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/security/src/main/java/org/apache/syncope/server/security/SecureRandomUtil.java
----------------------------------------------------------------------
diff --git a/syncope620/server/security/src/main/java/org/apache/syncope/server/security/SecureRandomUtil.java b/syncope620/server/security/src/main/java/org/apache/syncope/server/security/SecureRandomUtil.java
new file mode 100644
index 0000000..3f2735a
--- /dev/null
+++ b/syncope620/server/security/src/main/java/org/apache/syncope/server/security/SecureRandomUtil.java
@@ -0,0 +1,44 @@
+/*
+ * 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.server.security;
+
+import java.security.SecureRandom;
+
+import org.apache.commons.lang3.RandomStringUtils;
+
+public class SecureRandomUtil {
+    
+    private static final SecureRandom RANDOM = new SecureRandom();
+
+    public static String generateRandomPassword(final int tokenLength) {
+        return RandomStringUtils.random(tokenLength, 0, 0, true, false, null, RANDOM);
+    }
+    
+    public static String generateRandomLetter() {
+        return RandomStringUtils.random(1, 0, 0, true, false, null, RANDOM);
+    }
+    
+    public static String generateRandomNumber() {
+        return RandomStringUtils.random(1, 0, 0, false, true, null, RANDOM);
+    }
+    
+    public static String generateRandomSpecialCharacter(char[] characters) {
+        return RandomStringUtils.random(1, 0, 0, false, false, characters, RANDOM);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/security/src/main/resources/security.properties
----------------------------------------------------------------------
diff --git a/syncope620/server/security/src/main/resources/security.properties b/syncope620/server/security/src/main/resources/security.properties
new file mode 100644
index 0000000..c0fcd37
--- /dev/null
+++ b/syncope620/server/security/src/main/resources/security.properties
@@ -0,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.
+adminUser=admin
+adminPassword=5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
+adminPasswordAlgorithm=SHA1
+
+anonymousUser=${anonymousUser}
+anonymousKey=${anonymousKey}
+
+secretKey=${secretKey}
+# default for LDAP / RFC2307 SSHA
+digester.saltIterations=1
+digester.saltSizeBytes=8
+digester.invertPositionOfPlainSaltInEncryptionResults=true
+digester.invertPositionOfSaltInMessageBeforeDigesting=true
+digester.useLenientSaltSizeCheck=true
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/spring/pom.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/spring/pom.xml b/syncope620/server/spring/pom.xml
new file mode 100644
index 0000000..ef9ae41
--- /dev/null
+++ b/syncope620/server/spring/pom.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.syncope</groupId>
+    <artifactId>syncope-server</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Server Spring Extensions</name>
+  <description>Apache Syncope Server Spring Extensions</description>
+  <groupId>org.apache.syncope.server</groupId>
+  <artifactId>syncope-server-spring</artifactId>
+  <packaging>jar</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+    </dependency>
+      
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context</artifactId>
+    </dependency>
+  </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/spring/src/main/java/org/apache/syncope/server/spring/ApplicationContextProvider.java
----------------------------------------------------------------------
diff --git a/syncope620/server/spring/src/main/java/org/apache/syncope/server/spring/ApplicationContextProvider.java b/syncope620/server/spring/src/main/java/org/apache/syncope/server/spring/ApplicationContextProvider.java
new file mode 100644
index 0000000..0ffba20
--- /dev/null
+++ b/syncope620/server/spring/src/main/java/org/apache/syncope/server/spring/ApplicationContextProvider.java
@@ -0,0 +1,47 @@
+/*
+ * 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.server.spring;
+
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ConfigurableApplicationContext;
+
+public class ApplicationContextProvider implements ApplicationContextAware {
+
+    private static ConfigurableApplicationContext ctx;
+
+    public static ConfigurableApplicationContext getApplicationContext() {
+        return ctx;
+    }
+
+    public static DefaultListableBeanFactory getBeanFactory() {
+        return (DefaultListableBeanFactory) ctx.getBeanFactory();
+    }
+
+    /**
+     * Wiring the ApplicationContext into a static method.
+     *
+     * @param ctx Spring application context
+     */
+    @Override
+    public void setApplicationContext(final ApplicationContext ctx) {
+        ApplicationContextProvider.ctx = (ConfigurableApplicationContext) ctx;
+    }
+}


[26/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPATaskDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPATaskDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPATaskDAO.java
new file mode 100644
index 0000000..d1d9b15
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPATaskDAO.java
@@ -0,0 +1,185 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.persistence.Query;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.persistence.api.dao.TaskDAO;
+import org.apache.syncope.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.task.Task;
+import org.apache.syncope.persistence.jpa.entity.task.JPANotificationTask;
+import org.apache.syncope.persistence.jpa.entity.task.JPAPropagationTask;
+import org.apache.syncope.persistence.jpa.entity.task.JPAPushTask;
+import org.apache.syncope.persistence.jpa.entity.task.JPASchedTask;
+import org.apache.syncope.persistence.jpa.entity.task.JPASyncTask;
+import org.apache.syncope.persistence.jpa.entity.task.JPATask;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+@Repository
+public class JPATaskDAO extends AbstractDAO<Task, Long> implements TaskDAO {
+
+    @Override
+    public Class<? extends Task> getEntityReference(final TaskType type) {
+        Class<? extends Task> result = null;
+
+        switch (type) {
+            case NOTIFICATION:
+                result = JPANotificationTask.class;
+                break;
+
+            case PROPAGATION:
+                result = JPAPropagationTask.class;
+                break;
+
+            case PUSH:
+                result = JPAPushTask.class;
+                break;
+
+            case SCHEDULED:
+                result = JPASchedTask.class;
+                break;
+
+            case SYNCHRONIZATION:
+                result = JPASyncTask.class;
+                break;
+
+            default:
+        }
+
+        return result;
+    }
+
+    @Transactional(readOnly = true)
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Task> T find(final Long key) {
+        return (T) entityManager.find(JPATask.class, key);
+    }
+
+    private <T extends Task> StringBuilder buildfindAllQuery(final TaskType type) {
+        return new StringBuilder("SELECT e FROM ").
+                append(getEntityReference(type).getSimpleName()).
+                append(" e WHERE e.type=:type ");
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T extends Task> List<T> findToExec(final TaskType type) {
+        StringBuilder queryString = buildfindAllQuery(type).append("AND ");
+
+        if (type == TaskType.NOTIFICATION) {
+            queryString.append("e.executed = 0 ");
+        } else {
+            queryString.append("e.executions IS EMPTY ");
+        }
+        queryString.append("ORDER BY e.id DESC");
+
+        Query query = entityManager.createQuery(queryString.toString());
+        query.setParameter("type", type);
+        return query.getResultList();
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T extends Task> List<T> findAll(final ExternalResource resource, final TaskType type) {
+        StringBuilder queryString = buildfindAllQuery(type).append("AND e.resource=:resource ORDER BY e.id DESC");
+
+        final Query query = entityManager.createQuery(queryString.toString());
+        query.setParameter("type", type);
+        query.setParameter("resource", resource);
+
+        return query.getResultList();
+    }
+
+    @Override
+    public <T extends Task> List<T> findAll(final TaskType type) {
+        return findAll(-1, -1, Collections.<OrderByClause>emptyList(), type);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T extends Task> List<T> findAll(final int page, final int itemsPerPage,
+            final List<OrderByClause> orderByClauses, final TaskType type) {
+
+        StringBuilder queryString = buildfindAllQuery(type);
+        queryString.append(orderByClauses.isEmpty()
+                ? "ORDER BY e.id DESC"
+                : toOrderByStatement(getEntityReference(type), "e", orderByClauses));
+
+        Query query = entityManager.createQuery(queryString.toString());
+        query.setParameter("type", type);
+
+        query.setFirstResult(itemsPerPage * (page <= 0
+                ? 0
+                : page - 1));
+
+        if (itemsPerPage > 0) {
+            query.setMaxResults(itemsPerPage);
+        }
+
+        return query.getResultList();
+    }
+
+    @Override
+    public int count(final TaskType type) {
+        Query countQuery = entityManager.createNativeQuery("SELECT COUNT(id) FROM Task WHERE TYPE=?1");
+        countQuery.setParameter(1, type.toString());
+        return ((Number) countQuery.getSingleResult()).intValue();
+    }
+
+    @Transactional(rollbackFor = { Throwable.class })
+    @Override
+    public <T extends Task> T save(final T task) {
+        return entityManager.merge(task);
+    }
+
+    @Override
+    public void delete(final Long id) {
+        Task task = find(id);
+        if (task == null) {
+            return;
+        }
+
+        delete(task);
+    }
+
+    @Override
+    public void delete(final Task task) {
+        entityManager.remove(task);
+    }
+
+    @Override
+    public void deleteAll(final ExternalResource resource, final TaskType type) {
+        List<Task> tasks = findAll(resource, type);
+        if (tasks != null) {
+            List<Long> taskIds = new ArrayList<>(tasks.size());
+            for (Task task : tasks) {
+                taskIds.add(task.getKey());
+            }
+            for (Long taskId : taskIds) {
+                delete(taskId);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPATaskExecDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPATaskExecDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPATaskExecDAO.java
new file mode 100644
index 0000000..cc47a29
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPATaskExecDAO.java
@@ -0,0 +1,118 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.List;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.persistence.api.dao.TaskDAO;
+import org.apache.syncope.persistence.api.dao.TaskExecDAO;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.entity.task.Task;
+import org.apache.syncope.persistence.api.entity.task.TaskExec;
+import org.apache.syncope.persistence.jpa.entity.task.JPATaskExec;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+@Repository
+public class JPATaskExecDAO extends AbstractDAO<TaskExec, Long> implements TaskExecDAO {
+
+    @Autowired
+    private TaskDAO taskDAO;
+
+    @Override
+    public TaskExec find(final Long key) {
+        return entityManager.find(JPATaskExec.class, key);
+    }
+
+    private <T extends Task> TaskExec findLatest(final T task, final String field) {
+        TypedQuery<TaskExec> query = entityManager.createQuery(
+                "SELECT e FROM " + JPATaskExec.class.getSimpleName() + " e "
+                + "WHERE e.task=:task "
+                + "ORDER BY e." + field + " DESC", TaskExec.class);
+        query.setParameter("task", task);
+        query.setMaxResults(1);
+
+        List<TaskExec> result = query.getResultList();
+        return result == null || result.isEmpty()
+                ? null
+                : result.iterator().next();
+    }
+
+    @Override
+    public <T extends Task> TaskExec findLatestStarted(final T task) {
+        return findLatest(task, "startDate");
+    }
+
+    @Override
+    public <T extends Task> TaskExec findLatestEnded(final T task) {
+        return findLatest(task, "endDate");
+    }
+
+    @Override
+    public List<TaskExec> findAll(final TaskType type) {
+        StringBuilder queryString = new StringBuilder("SELECT e FROM ").append(JPATaskExec.class.getSimpleName()).
+                append(" e WHERE e.task IN (").append("SELECT t FROM ").
+                append(taskDAO.getEntityReference(type).getSimpleName()).append(" t)");
+
+        TypedQuery<TaskExec> query = entityManager.createQuery(queryString.toString(), TaskExec.class);
+        return query.getResultList();
+    }
+
+    @Override
+    public TaskExec save(final TaskExec execution) {
+        return entityManager.merge(execution);
+    }
+
+    /**
+     * This method has an explicit Transactional annotation because it is called by
+     * {@link org.apache.syncope.core.quartz.AbstractTaskJob#execute(org.quartz.JobExecutionContext) }.
+     *
+     * @param taskId task id
+     * @param execution task execution
+     * @throws InvalidEntityException if any bean validation fails
+     */
+    @Override
+    @Transactional(rollbackFor = { Throwable.class })
+    public void saveAndAdd(final Long taskId, final TaskExec execution) throws InvalidEntityException {
+        Task task = taskDAO.find(taskId);
+        task.addExec(execution);
+        taskDAO.save(task);
+    }
+
+    @Override
+    public void delete(final Long id) {
+        TaskExec execution = find(id);
+        if (execution == null) {
+            return;
+        }
+
+        delete(execution);
+    }
+
+    @Override
+    public void delete(final TaskExec execution) {
+        if (execution.getTask() != null) {
+            execution.getTask().removeExec(execution);
+        }
+
+        entityManager.remove(execution);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAUserDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAUserDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAUserDAO.java
new file mode 100644
index 0000000..2c141a6
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAUserDAO.java
@@ -0,0 +1,225 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.SubjectType;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.dao.SubjectSearchDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.dao.search.AttributeCond;
+import org.apache.syncope.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.persistence.api.dao.search.SubjectCond;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.Subject;
+import org.apache.syncope.persistence.api.entity.VirAttr;
+import org.apache.syncope.persistence.api.entity.membership.Membership;
+import org.apache.syncope.persistence.api.entity.user.SecurityQuestion;
+import org.apache.syncope.persistence.api.entity.user.UDerAttr;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttr;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttrValue;
+import org.apache.syncope.persistence.api.entity.user.UVirAttr;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.entity.JPAAttributableUtil;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUser;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class JPAUserDAO extends AbstractSubjectDAO<UPlainAttr, UDerAttr, UVirAttr> implements UserDAO {
+
+    @Autowired
+    private SubjectSearchDAO searchDAO;
+
+    @Autowired
+    private RoleDAO roleDAO;
+
+    @Override
+    protected Subject<UPlainAttr, UDerAttr, UVirAttr> findInternal(Long key) {
+        return find(key);
+    }
+
+    @Override
+    public User find(final Long key) {
+        TypedQuery<User> query = entityManager.createQuery(
+                "SELECT e FROM " + JPAUser.class.getSimpleName() + " e WHERE e.id = :id", User.class);
+        query.setParameter("id", key);
+
+        User result = null;
+        try {
+            result = query.getSingleResult();
+        } catch (NoResultException e) {
+            LOG.debug("No user found with id {}", key, e);
+        }
+
+        return result;
+    }
+
+    @Override
+    public User find(final String username) {
+        TypedQuery<User> query = entityManager.createQuery("SELECT e FROM " + JPAUser.class.getSimpleName()
+                + " e WHERE e.username = :username", User.class);
+        query.setParameter("username", username);
+
+        User result = null;
+        try {
+            result = query.getSingleResult();
+        } catch (NoResultException e) {
+            LOG.debug("No user found with username {}", username, e);
+        }
+
+        return result;
+    }
+
+    @Override
+    public User findByWorkflowId(final String workflowId) {
+        TypedQuery<User> query = entityManager.createQuery("SELECT e FROM " + JPAUser.class.getSimpleName()
+                + " e WHERE e.workflowId = :workflowId", User.class);
+        query.setParameter("workflowId", workflowId);
+
+        User result = null;
+        try {
+            result = query.getSingleResult();
+        } catch (NoResultException e) {
+            LOG.debug("No user found with workflow id {}", workflowId, e);
+        }
+
+        return result;
+    }
+
+    @Override
+    public User findByToken(final String token) {
+        TypedQuery<User> query = entityManager.createQuery("SELECT e FROM " + JPAUser.class.getSimpleName()
+                + " e WHERE e.token = :token", User.class);
+        query.setParameter("token", token);
+
+        User result = null;
+        try {
+            result = query.getSingleResult();
+        } catch (NoResultException e) {
+            LOG.debug("No user found with token {}", token, e);
+        }
+
+        return result;
+    }
+
+    @Override
+    public List<User> findBySecurityQuestion(final SecurityQuestion securityQuestion) {
+        TypedQuery<User> query = entityManager.createQuery("SELECT e FROM " + JPAUser.class.getSimpleName()
+                + " e WHERE e.securityQuestion = :securityQuestion", User.class);
+        query.setParameter("securityQuestion", securityQuestion);
+
+        return query.getResultList();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<User> findByAttrValue(final String schemaName, final UPlainAttrValue attrValue) {
+        return (List<User>) findByAttrValue(
+                schemaName, attrValue, JPAAttributableUtil.getInstance(AttributableType.USER));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public User findByAttrUniqueValue(final String schemaName, final UPlainAttrValue attrUniqueValue) {
+        return (User) findByAttrUniqueValue(schemaName, attrUniqueValue,
+                JPAAttributableUtil.getInstance(AttributableType.USER));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<User> findByDerAttrValue(final String schemaName, final String value) {
+        return (List<User>) findByDerAttrValue(
+                schemaName, value, JPAAttributableUtil.getInstance(AttributableType.USER));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<User> findByResource(final ExternalResource resource) {
+        return (List<User>) findByResource(resource, JPAAttributableUtil.getInstance(AttributableType.USER));
+    }
+
+    @Override
+    public final List<User> findAll(final Set<Long> adminRoles, final int page, final int itemsPerPage) {
+        return findAll(adminRoles, page, itemsPerPage, Collections.<OrderByClause>emptyList());
+    }
+
+    private SearchCond getAllMatchingCond() {
+        SubjectCond idCond = new SubjectCond(AttributeCond.Type.ISNOTNULL);
+        idCond.setSchema("id");
+        return SearchCond.getLeafCond(idCond);
+    }
+
+    @Override
+    public List<User> findAll(final Set<Long> adminRoles,
+            final int page, final int itemsPerPage, final List<OrderByClause> orderBy) {
+
+        return searchDAO.search(
+                adminRoles, getAllMatchingCond(), page, itemsPerPage, orderBy, SubjectType.USER);
+    }
+
+    @Override
+    public final int count(final Set<Long> adminRoles) {
+        return searchDAO.count(adminRoles, getAllMatchingCond(), SubjectType.USER);
+    }
+
+    @Override
+    public User save(final User user) {
+        final User merged = entityManager.merge(user);
+        for (VirAttr virAttr : merged.getVirAttrs()) {
+            virAttr.getValues().clear();
+            virAttr.getValues().addAll(user.getVirAttr(virAttr.getSchema().getKey()).getValues());
+        }
+
+        return merged;
+    }
+
+    @Override
+    public void delete(final Long key) {
+        User user = (User) findInternal(key);
+        if (user == null) {
+            return;
+        }
+
+        delete(user);
+    }
+
+    @Override
+    public void delete(final User user) {
+        // Not calling membershipDAO.delete() here because it would try to save this user as well, thus going into
+        // ConcurrentModificationException
+        for (Membership membership : user.getMemberships()) {
+            membership.setUser(null);
+
+            roleDAO.save(membership.getRole());
+            membership.setRole(null);
+
+            entityManager.remove(membership);
+        }
+        user.getMemberships().clear();
+
+        entityManager.remove(user);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAVirAttrDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAVirAttrDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAVirAttrDAO.java
new file mode 100644
index 0000000..62a1185
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAVirAttrDAO.java
@@ -0,0 +1,86 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.List;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.persistence.api.dao.VirAttrDAO;
+import org.apache.syncope.persistence.api.entity.Subject;
+import org.apache.syncope.persistence.api.entity.VirAttr;
+import org.apache.syncope.persistence.api.entity.membership.MVirAttr;
+import org.apache.syncope.persistence.api.entity.role.RVirAttr;
+import org.apache.syncope.persistence.api.entity.user.UVirAttr;
+import org.apache.syncope.persistence.jpa.entity.AbstractVirAttr;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMVirAttr;
+import org.apache.syncope.persistence.jpa.entity.role.JPARVirAttr;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUVirAttr;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class JPAVirAttrDAO extends AbstractDAO<VirAttr, Long> implements VirAttrDAO {
+
+    public <T extends VirAttr> Class<? extends AbstractVirAttr> getJPAEntityReference(
+            final Class<T> reference) {
+
+        return RVirAttr.class.isAssignableFrom(reference)
+                ? JPARVirAttr.class
+                : MVirAttr.class.isAssignableFrom(reference)
+                        ? JPAMVirAttr.class
+                        : UVirAttr.class.isAssignableFrom(reference)
+                                ? JPAUVirAttr.class
+                                : null;
+    }
+
+    @Override
+    public <T extends VirAttr> T find(final Long key, final Class<T> reference) {
+        return reference.cast(entityManager.find(getJPAEntityReference(reference), key));
+    }
+
+    @Override
+    public <T extends VirAttr> List<T> findAll(final Class<T> reference) {
+        TypedQuery<T> query = entityManager.createQuery(
+                "SELECT e FROM " + getJPAEntityReference(reference).getSimpleName() + " e", reference);
+        return query.getResultList();
+    }
+
+    @Override
+    public <T extends VirAttr> T save(final T virAttr) {
+        return entityManager.merge(virAttr);
+    }
+
+    @Override
+    public <T extends VirAttr> void delete(final Long key, final Class<T> reference) {
+        T virAttr = find(key, reference);
+        if (virAttr == null) {
+            return;
+        }
+
+        delete(virAttr);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T extends VirAttr> void delete(final T virAttr) {
+        if (virAttr.getOwner() != null) {
+            ((Subject<?, ?, T>) virAttr.getOwner()).removeVirAttr(virAttr);
+        }
+
+        entityManager.remove(virAttr);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAVirSchemaDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAVirSchemaDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAVirSchemaDAO.java
new file mode 100644
index 0000000..c0311f2
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAVirSchemaDAO.java
@@ -0,0 +1,131 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.persistence.api.dao.AttrTemplateDAO;
+import org.apache.syncope.persistence.api.dao.ExternalResourceDAO;
+import org.apache.syncope.persistence.api.dao.VirAttrDAO;
+import org.apache.syncope.persistence.api.dao.VirSchemaDAO;
+import org.apache.syncope.persistence.api.entity.AttributableUtil;
+import org.apache.syncope.persistence.api.entity.VirAttr;
+import org.apache.syncope.persistence.api.entity.VirSchema;
+import org.apache.syncope.persistence.api.entity.membership.MVirSchema;
+import org.apache.syncope.persistence.api.entity.role.RVirSchema;
+import org.apache.syncope.persistence.api.entity.user.UMappingItem;
+import org.apache.syncope.persistence.api.entity.user.UVirAttr;
+import org.apache.syncope.persistence.api.entity.user.UVirSchema;
+import org.apache.syncope.persistence.jpa.entity.AbstractVirSchema;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMVirSchema;
+import org.apache.syncope.persistence.jpa.entity.role.JPARVirSchema;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUVirSchema;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class JPAVirSchemaDAO extends AbstractDAO<VirSchema, String> implements VirSchemaDAO {
+
+    @Autowired
+    private VirAttrDAO virAttrDAO;
+
+    @Autowired
+    private AttrTemplateDAO<VirSchema> attrTemplateDAO;
+
+    @Autowired
+    private ExternalResourceDAO resourceDAO;
+
+    private <T extends VirSchema> Class<? extends AbstractVirSchema> getJPAEntityReference(final Class<T> reference) {
+        return RVirSchema.class.isAssignableFrom(reference)
+                ? JPARVirSchema.class
+                : MVirSchema.class.isAssignableFrom(reference)
+                        ? JPAMVirSchema.class
+                        : UVirSchema.class.isAssignableFrom(reference)
+                                ? JPAUVirSchema.class
+                                : null;
+    }
+
+    @Override
+    public <T extends VirSchema> T find(final String key, final Class<T> reference) {
+        return reference.cast(entityManager.find(getJPAEntityReference(reference), key));
+    }
+
+    @Override
+    public <T extends VirSchema> List<T> findAll(final Class<T> reference) {
+        TypedQuery<T> query = entityManager.createQuery(
+                "SELECT e FROM " + getJPAEntityReference(reference).getSimpleName() + " e", reference);
+        return query.getResultList();
+    }
+
+    @Override
+    public <T extends VirAttr> List<T> findAttrs(final VirSchema schema, final Class<T> reference) {
+        final StringBuilder queryString = new StringBuilder("SELECT e FROM ").
+                append(((JPAVirAttrDAO) virAttrDAO).getJPAEntityReference(reference).getSimpleName()).
+                append(" e WHERE e.");
+        if (UVirAttr.class.isAssignableFrom(reference)) {
+            queryString.append("virSchema");
+        } else {
+            queryString.append("template.schema");
+        }
+        queryString.append("=:schema");
+
+        TypedQuery<T> query = entityManager.createQuery(queryString.toString(), reference);
+        query.setParameter("schema", schema);
+
+        return query.getResultList();
+    }
+
+    @Override
+    public <T extends VirSchema> T save(final T virSchema) {
+        return entityManager.merge(virSchema);
+    }
+
+    @Override
+    public void delete(final String name, final AttributableUtil attributableUtil) {
+        final VirSchema schema = find(name, attributableUtil.virSchemaClass());
+        if (schema == null) {
+            return;
+        }
+
+        final Set<Long> attrIds = new HashSet<>();
+        for (VirAttr attr : findAttrs(schema, attributableUtil.virAttrClass())) {
+            attrIds.add(attr.getKey());
+        }
+        for (Long attrId : attrIds) {
+            virAttrDAO.delete(attrId, attributableUtil.virAttrClass());
+        }
+
+        if (attributableUtil.getType() != AttributableType.USER) {
+            for (Iterator<Number> it = attrTemplateDAO.
+                    findBySchemaName(schema.getKey(), attributableUtil.virAttrTemplateClass()).iterator();
+                    it.hasNext();) {
+
+                attrTemplateDAO.delete(it.next().longValue(), attributableUtil.virAttrTemplateClass());
+            }
+        }
+
+        resourceDAO.deleteMapping(name, attributableUtil.virIntMappingType(), UMappingItem.class);
+
+        entityManager.remove(schema);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/OrderBySupport.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/OrderBySupport.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/OrderBySupport.java
new file mode 100644
index 0000000..aafaf0e
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/OrderBySupport.java
@@ -0,0 +1,47 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+class OrderBySupport {
+
+    static class Item {
+
+        protected String select;
+
+        protected String where;
+
+        protected String orderBy;
+
+        protected boolean isEmpty() {
+            return (select == null || select.isEmpty())
+                    && (where == null || where.isEmpty())
+                    && (orderBy == null || orderBy.isEmpty());
+        }
+    }
+
+    protected Set<SearchSupport.SearchView> views = new HashSet<>();
+
+    protected List<Item> items = new ArrayList<>();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/SearchSupport.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/SearchSupport.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/SearchSupport.java
new file mode 100644
index 0000000..2e2c7a7
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/SearchSupport.java
@@ -0,0 +1,132 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.SubjectType;
+
+class SearchSupport {
+
+    static class SearchView {
+
+        protected String alias;
+
+        protected String name;
+
+        protected SearchView(final String alias, final String name) {
+            this.alias = alias;
+            this.name = name;
+        }
+
+        @Override
+        public boolean equals(final Object obj) {
+            return EqualsBuilder.reflectionEquals(this, obj);
+        }
+
+        @Override
+        public int hashCode() {
+            return HashCodeBuilder.reflectionHashCode(this);
+        }
+    }
+
+    private final SubjectType type;
+
+    public SearchSupport(final SubjectType type) {
+        this.type = type;
+    }
+
+    public String fieldName(final AttrSchemaType type) {
+        String result;
+
+        switch (type) {
+            case Boolean:
+                result = "booleanvalue";
+                break;
+
+            case Date:
+                result = "datevalue";
+                break;
+
+            case Double:
+                result = "doublevalue";
+                break;
+
+            case Long:
+                result = "longvalue";
+                break;
+
+            case String:
+            case Enum:
+                result = "stringvalue";
+                break;
+
+            default:
+                result = null;
+        }
+
+        return result;
+    }
+
+    public SearchView field() {
+        String result = "";
+
+        switch (type) {
+            case USER:
+            default:
+                result = "user_search";
+                break;
+
+            case ROLE:
+                result = "role_search";
+                break;
+        }
+
+        return new SearchView("sv", result);
+    }
+
+    public SearchView attr() {
+        return new SearchView("sva", field().name + "_attr");
+    }
+
+    public SearchView membership() {
+        return new SearchView("svm", field().name + "_membership");
+    }
+
+    public SearchView nullAttr() {
+        return new SearchView("svna", field().name + "_null_attr");
+    }
+
+    public SearchView resource() {
+        return new SearchView("svr", field().name + "_resource");
+    }
+
+    public SearchView roleResource() {
+        return new SearchView("svrr", field().name + "_role_resource");
+    }
+
+    public SearchView uniqueAttr() {
+        return new SearchView("svua", field().name + "_unique_attr");
+    }
+
+    public SearchView entitlements() {
+        return new SearchView("sve", field().name + "_entitlements");
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractAnnotatedEntity.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractAnnotatedEntity.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractAnnotatedEntity.java
new file mode 100644
index 0000000..1497676
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractAnnotatedEntity.java
@@ -0,0 +1,113 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import java.util.Date;
+import javax.persistence.Column;
+import javax.persistence.EntityListeners;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import org.apache.syncope.persistence.api.entity.AnnotatedEntity;
+
+/**
+ * Abstract wrapper for common system information.
+ */
+@MappedSuperclass
+@EntityListeners(value = AnnotatedEntityListener.class)
+public abstract class AbstractAnnotatedEntity<KEY> extends AbstractEntity<KEY> implements AnnotatedEntity<KEY> {
+
+    private static final long serialVersionUID = -4801685541488201219L;
+
+    /**
+     * Username of the user that has created this profile.
+     * <br/>
+     * Reference to existing user cannot be used: the creator can either be <tt>admin</tt> or was deleted.
+     */
+    @Column(nullable = false)
+    private String creator;
+
+    /**
+     * Creation date.
+     */
+    @Column(nullable = false)
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date creationDate;
+
+    /**
+     * Username of the user that has performed the last modification to this profile.
+     * <br/>
+     * This field cannot be null: at creation time it needs to be initialized with the creator username.
+     * <br/>
+     * The modifier can be the user itself if the last performed change was a self-modification.
+     * <br/>
+     * Reference to existing user cannot be used: the creator can either be <tt>admin</tt> or was deleted.
+     */
+    @Column(nullable = false)
+    private String lastModifier;
+
+    /**
+     * Last change date.
+     * <br/>
+     * This field cannot be null: at creation time it needs to be initialized with <tt>creationDate</tt> field value.
+     */
+    @Column(nullable = false)
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date lastChangeDate;
+
+    @Override
+    public String getCreator() {
+        return creator;
+    }
+
+    @Override
+    public void setCreator(final String creator) {
+        this.creator = creator;
+    }
+
+    @Override
+    public Date getCreationDate() {
+        return creationDate == null ? null : new Date(creationDate.getTime());
+    }
+
+    @Override
+    public void setCreationDate(final Date creationDate) {
+        this.creationDate = creationDate == null ? null : new Date(creationDate.getTime());
+    }
+
+    @Override
+    public String getLastModifier() {
+        return lastModifier;
+    }
+
+    @Override
+    public void setLastModifier(final String lastModifier) {
+        this.lastModifier = lastModifier;
+    }
+
+    @Override
+    public Date getLastChangeDate() {
+        return lastChangeDate == null ? creationDate : lastChangeDate;
+    }
+
+    @Override
+    public void setLastChangeDate(final Date lastChangeDate) {
+        this.lastChangeDate = lastChangeDate == null ? null : new Date(lastChangeDate.getTime());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractAttrTemplate.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractAttrTemplate.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractAttrTemplate.java
new file mode 100644
index 0000000..d3b6590
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractAttrTemplate.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.persistence.jpa.entity;
+
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.MappedSuperclass;
+import org.apache.syncope.persistence.api.entity.AttrTemplate;
+import org.apache.syncope.persistence.api.entity.Schema;
+
+@MappedSuperclass
+public abstract class AbstractAttrTemplate<S extends Schema> extends AbstractEntity<Long> implements AttrTemplate<S> {
+
+    private static final long serialVersionUID = 4829112252713766666L;
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.AUTO)
+    protected Long id;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractAttributable.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractAttributable.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractAttributable.java
new file mode 100644
index 0000000..a6398cf
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractAttributable.java
@@ -0,0 +1,106 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.syncope.persistence.api.entity.Attributable;
+import org.apache.syncope.persistence.api.entity.DerAttr;
+import org.apache.syncope.persistence.api.entity.DerSchema;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.apache.syncope.persistence.api.entity.VirAttr;
+import org.apache.syncope.persistence.api.entity.VirSchema;
+
+public abstract class AbstractAttributable<P extends PlainAttr, D extends DerAttr, V extends VirAttr>
+        extends AbstractAnnotatedEntity<Long> implements Attributable<P, D, V> {
+
+    private static final long serialVersionUID = -4801685541488201119L;
+
+    @Override
+    public P getPlainAttr(final String plainSchemaName) {
+        P result = null;
+        for (P plainAttr : getPlainAttrs()) {
+            if (plainAttr != null && plainAttr.getSchema() != null
+                    && plainSchemaName.equals(plainAttr.getSchema().getKey())) {
+
+                result = plainAttr;
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public D getDerAttr(final String derSchemaName) {
+        D result = null;
+        for (D derAttr : getDerAttrs()) {
+            if (derAttr != null && derAttr.getSchema() != null
+                    && derSchemaName.equals(derAttr.getSchema().getKey())) {
+
+                result = derAttr;
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public V getVirAttr(final String virSchemaName) {
+        V result = null;
+        for (V virAttr : getVirAttrs()) {
+            if (virAttr != null && virAttr.getSchema() != null
+                    && virSchemaName.equals(virAttr.getSchema().getKey())) {
+
+                result = virAttr;
+            }
+        }
+
+        return result;
+    }
+
+    protected Map<PlainSchema, P> getPlainAttrMap() {
+        final Map<PlainSchema, P> map = new HashMap<>();
+
+        for (P attr : getPlainAttrs()) {
+            map.put(attr.getSchema(), attr);
+        }
+
+        return map;
+    }
+
+    protected Map<DerSchema, D> getDerAttrMap() {
+        final Map<DerSchema, D> map = new HashMap<>();
+
+        for (D attr : getDerAttrs()) {
+            map.put(attr.getSchema(), attr);
+        }
+
+        return map;
+    }
+
+    protected Map<VirSchema, V> getVirAttrMap() {
+        final Map<VirSchema, V> map = new HashMap<>();
+
+        for (V attr : getVirAttrs()) {
+            map.put(attr.getSchema(), attr);
+        }
+
+        return map;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractDerAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractDerAttr.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractDerAttr.java
new file mode 100644
index 0000000..4e1eb4d
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractDerAttr.java
@@ -0,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.persistence.jpa.entity;
+
+import java.util.Collection;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.MappedSuperclass;
+import org.apache.syncope.persistence.api.entity.DerAttr;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.server.utils.jexl.JexlUtil;
+
+@MappedSuperclass
+public abstract class AbstractDerAttr extends AbstractEntity<Long> implements DerAttr {
+
+    private static final long serialVersionUID = 4740924251090424771L;
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.AUTO)
+    protected Long id;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    /**
+     * @param attributes the set of attributes against which evaluate this derived attribute
+     * @return the value of this derived attribute
+     */
+    @Override
+    public String getValue(final Collection<? extends PlainAttr> attributes) {
+        return JexlUtil.evaluate(getSchema().getExpression(), getOwner(), attributes);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractDerSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractDerSchema.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractDerSchema.java
new file mode 100644
index 0000000..e348aa7
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractDerSchema.java
@@ -0,0 +1,85 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Id;
+import javax.persistence.MappedSuperclass;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.persistence.api.entity.DerSchema;
+import org.apache.syncope.persistence.jpa.validation.entity.SchemaNameCheck;
+
+@MappedSuperclass
+@SchemaNameCheck
+public abstract class AbstractDerSchema extends AbstractEntity<String> implements DerSchema {
+
+    private static final long serialVersionUID = -6173643493348674060L;
+
+    @Id
+    private String name;
+
+    @Column(nullable = false)
+    private String expression;
+
+    @Override
+    public String getKey() {
+        return name;
+    }
+
+    @Override
+    public void setKey(final String key) {
+        this.name = key;
+    }
+
+    @Override
+    public String getExpression() {
+        return expression;
+    }
+
+    @Override
+    public void setExpression(final String expression) {
+        this.expression = expression;
+    }
+
+    @Override
+    public AttrSchemaType getType() {
+        return AttrSchemaType.String;
+    }
+
+    @Override
+    public String getMandatoryCondition() {
+        return Boolean.FALSE.toString().toLowerCase();
+    }
+
+    @Override
+    public boolean isMultivalue() {
+        return Boolean.TRUE;
+    }
+
+    @Override
+    public boolean isUniqueConstraint() {
+        return Boolean.FALSE;
+    }
+
+    @Override
+    public boolean isReadonly() {
+        return Boolean.FALSE;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractEntity.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractEntity.java
new file mode 100644
index 0000000..720b62b
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractEntity.java
@@ -0,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.persistence.jpa.entity;
+
+import java.beans.PropertyDescriptor;
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.syncope.persistence.api.entity.Entity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
+
+public abstract class AbstractEntity<KEY> implements Entity<KEY>, Serializable {
+
+    private static final long serialVersionUID = -9017214159540857901L;
+
+    /**
+     * Logger.
+     */
+    protected static final Logger LOG = LoggerFactory.getLogger(AbstractEntity.class);
+
+    protected void checkType(final Object object, final Class<?> clazz) {
+        if (object !=null && !clazz.isInstance(object)) {
+            throw new ClassCastException("Expected " + clazz.getName() + ", got " + object.getClass().getName());
+        }
+    }
+
+    /**
+     * @param property the integer representing a boolean value
+     * @return the boolean value corresponding to the property param
+     */
+    public final boolean isBooleanAsInteger(final Integer property) {
+        return property != null && property == 1;
+    }
+
+    /**
+     * @param value the boolean value to be represented as integer
+     * @return the integer corresponding to the property param
+     */
+    public final Integer getBooleanAsInteger(final Boolean value) {
+        return Boolean.TRUE.equals(value)
+                ? 1
+                : 0;
+    }
+
+    /**
+     * @return fields to be excluded when computing equals() or hashcode()
+     */
+    private String[] getExcludeFields() {
+        Set<String> excludeFields = new HashSet<>();
+
+        for (PropertyDescriptor propDesc : BeanUtils.getPropertyDescriptors(getClass())) {
+            if (propDesc.getPropertyType().isInstance(Collections.emptySet())
+                    || propDesc.getPropertyType().isInstance(Collections.emptyList())) {
+
+                excludeFields.add(propDesc.getName());
+            }
+        }
+
+        return excludeFields.toArray(new String[] {});
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        return EqualsBuilder.reflectionEquals(this, obj, getExcludeFields());
+    }
+
+    @Override
+    public int hashCode() {
+        return HashCodeBuilder.reflectionHashCode(this, getExcludeFields());
+    }
+
+    @Override
+    public String toString() {
+        Method method = BeanUtils.findMethod(getClass(), "getKey");
+
+        StringBuilder result = new StringBuilder().append(getClass().getSimpleName()).append('[');
+        if (method != null) {
+            try {
+                result.append(method.invoke(this));
+            } catch (Exception e) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.error("While serializing to string", e);
+                }
+            }
+        }
+        result.append(']');
+
+        return result.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractExec.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractExec.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractExec.java
new file mode 100644
index 0000000..0d62824
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractExec.java
@@ -0,0 +1,114 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Lob;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import org.apache.syncope.persistence.api.entity.Exec;
+
+@MappedSuperclass
+public abstract class AbstractExec extends AbstractEntity<Long> implements Exec {
+
+    private static final long serialVersionUID = -812344822970166317L;
+
+    @Column(nullable = false)
+    protected String status;
+
+    /**
+     * Any information to be accompanied to this execution's result.
+     */
+    @Lob
+    protected String message;
+
+    /**
+     * Start instant of this execution.
+     */
+    @Temporal(TemporalType.TIMESTAMP)
+    protected Date startDate;
+
+    /**
+     * End instant of this execution.
+     */
+    @Temporal(TemporalType.TIMESTAMP)
+    protected Date endDate;
+
+    @Override
+    public String getStatus() {
+        return status;
+    }
+
+    @Override
+    public void setStatus(final String status) {
+        this.status = status;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    /**
+     * Set a message for this execution, taking care of replacing every null character with newline.
+     *
+     * @param message the message to set for this execution
+     */
+    @Override
+    public void setMessage(String message) {
+        if (message != null) {
+            message = message.replace('\0', '\n');
+        }
+        this.message = message;
+    }
+
+    @Override
+    public Date getEndDate() {
+        return endDate == null
+                ? null
+                : new Date(endDate.getTime());
+    }
+
+    @Override
+
+    public void setEndDate(final Date endDate) {
+        this.endDate = endDate == null
+                ? null
+                : new Date(endDate.getTime());
+    }
+
+    @Override
+
+    public Date getStartDate() {
+        return startDate == null
+                ? null
+                : new Date(startDate.getTime());
+    }
+
+    @Override
+
+    public void setStartDate(final Date startDate) {
+        this.startDate = startDate == null
+                ? null
+                : new Date(startDate.getTime());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractMapping.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractMapping.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractMapping.java
new file mode 100644
index 0000000..f48a2bb
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractMapping.java
@@ -0,0 +1,76 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import javax.persistence.Cacheable;
+import javax.persistence.MappedSuperclass;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.persistence.api.entity.Mapping;
+import org.apache.syncope.persistence.api.entity.MappingItem;
+
+@MappedSuperclass
+@Cacheable
+public abstract class AbstractMapping<T extends MappingItem> extends AbstractEntity<Long> implements Mapping<T> {
+
+    private static final long serialVersionUID = 4316047254916259158L;
+
+    /**
+     * A JEXL expression for determining how to find the account id in external resource's space.
+     */
+    private String accountLink;
+
+    @Override
+    public String getAccountLink() {
+        return accountLink;
+    }
+
+    @Override
+    public void setAccountLink(final String accountLink) {
+        this.accountLink = accountLink;
+    }
+
+    @Override
+    public T getAccountIdItem() {
+        T accountIdItem = null;
+        for (T item : getItems()) {
+            if (item.isAccountid()) {
+                accountIdItem = item;
+            }
+        }
+        return accountIdItem;
+    }
+
+    protected boolean addAccountIdItem(final T accountIdItem) {
+        if (IntMappingType.UserVirtualSchema == accountIdItem.getIntMappingType()
+                || IntMappingType.RoleVirtualSchema == accountIdItem.getIntMappingType()
+                || IntMappingType.MembershipVirtualSchema == accountIdItem.getIntMappingType()
+                || IntMappingType.Password == accountIdItem.getIntMappingType()) {
+
+            throw new IllegalArgumentException("Virtual attributes cannot be set as accountId");
+        }
+        if (IntMappingType.Password == accountIdItem.getIntMappingType()) {
+            throw new IllegalArgumentException("Password attributes cannot be set as accountId");
+        }
+
+        accountIdItem.setExtAttrName(accountIdItem.getExtAttrName());
+        accountIdItem.setAccountid(true);
+
+        return this.addItem(accountIdItem);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractMappingItem.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractMappingItem.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractMappingItem.java
new file mode 100644
index 0000000..7ad5e97
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractMappingItem.java
@@ -0,0 +1,190 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import javax.persistence.Basic;
+import javax.persistence.Cacheable;
+import javax.persistence.Column;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.MappedSuperclass;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.persistence.api.entity.MappingItem;
+
+@MappedSuperclass
+@Cacheable
+public abstract class AbstractMappingItem extends AbstractEntity<Long> implements MappingItem {
+
+    private static final long serialVersionUID = 7383601853619332424L;
+
+    @Column(nullable = true)
+    private String intAttrName;
+
+    @Column(nullable = false)
+    @Enumerated(EnumType.STRING)
+    private IntMappingType intMappingType;
+
+    /**
+     * Target resource's field to be mapped.
+     */
+    @Column(nullable = true)
+    private String extAttrName;
+
+    /**
+     * Specify if the mapped target resource's field is nullable.
+     */
+    @Column(nullable = false)
+    private String mandatoryCondition;
+
+    /**
+     * Specify if the mapped target resource's field is the key.
+     */
+    @Column(nullable = false)
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer accountid;
+
+    /**
+     * Specify if the mapped target resource's field is the password.
+     */
+    @Column(nullable = false)
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer password;
+
+    /**
+     * Mapping purposes: SYNCHRONIZATION, PROPAGATION, BOTH.
+     */
+    @Column(nullable = false)
+    @Enumerated(EnumType.STRING)
+    private MappingPurpose purpose;
+
+    public AbstractMappingItem() {
+        super();
+
+        mandatoryCondition = Boolean.FALSE.toString();
+
+        accountid = getBooleanAsInteger(false);
+        password = getBooleanAsInteger(false);
+    }
+
+    @Override
+    public String getExtAttrName() {
+        return extAttrName;
+    }
+
+    @Override
+    public void setExtAttrName(final String extAttrName) {
+        this.extAttrName = extAttrName;
+    }
+
+    @Override
+    public String getMandatoryCondition() {
+        return mandatoryCondition;
+    }
+
+    @Override
+    public void setMandatoryCondition(final String mandatoryCondition) {
+        this.mandatoryCondition = mandatoryCondition;
+    }
+
+    @Override
+    public String getIntAttrName() {
+        final String name;
+
+        switch (getIntMappingType()) {
+            case UserId:
+            case RoleId:
+            case MembershipId:
+                name = "id";
+                break;
+
+            case Username:
+                name = "username";
+                break;
+
+            case Password:
+                name = "password";
+                break;
+
+            case RoleName:
+                name = "roleName";
+                break;
+
+            case RoleOwnerSchema:
+                name = "roleOwnerSchema";
+                break;
+
+            default:
+                name = intAttrName;
+        }
+
+        return name;
+    }
+
+    @Override
+    public void setIntAttrName(final String intAttrName) {
+        this.intAttrName = intAttrName;
+    }
+
+    @Override
+    public IntMappingType getIntMappingType() {
+        return intMappingType;
+    }
+
+    @Override
+    public void setIntMappingType(final IntMappingType intMappingType) {
+        this.intMappingType = intMappingType;
+    }
+
+    @Override
+    public boolean isAccountid() {
+        return isBooleanAsInteger(accountid);
+    }
+
+    @Override
+    public void setAccountid(final boolean accountid) {
+        this.accountid = getBooleanAsInteger(accountid);
+    }
+
+    @Override
+    public boolean isPassword() {
+        return isBooleanAsInteger(password);
+    }
+
+    @Override
+    public void setPassword(final boolean password) {
+        this.password = getBooleanAsInteger(password);
+    }
+
+    @Override
+    public MappingPurpose getPurpose() {
+        return purpose;
+    }
+
+    @Override
+    public void setPurpose(final MappingPurpose purpose) {
+        this.purpose = purpose;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractPlainAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractPlainAttr.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractPlainAttr.java
new file mode 100644
index 0000000..4c8f2db
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractPlainAttr.java
@@ -0,0 +1,81 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.persistence.MappedSuperclass;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidPlainAttrValueException;
+import org.apache.syncope.persistence.api.entity.AttributableUtil;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.PlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.persistence.jpa.validation.entity.PlainAttrCheck;
+
+@MappedSuperclass
+@PlainAttrCheck
+public abstract class AbstractPlainAttr extends AbstractEntity<Long> implements PlainAttr {
+
+    private static final long serialVersionUID = -9115431608821806124L;
+
+    protected abstract boolean addValue(PlainAttrValue attrValue);
+
+    @Override
+    public void addValue(final String value, final AttributableUtil attributableUtil)
+            throws InvalidPlainAttrValueException {
+
+        PlainAttrValue attrValue;
+        if (getSchema().isUniqueConstraint()) {
+            attrValue = attributableUtil.newPlainAttrUniqueValue();
+            ((PlainAttrUniqueValue) attrValue).setSchema(getSchema());
+        } else {
+            attrValue = attributableUtil.newPlainAttrValue();
+        }
+
+        attrValue.setAttr(this);
+        getSchema().getValidator().validate(value, attrValue);
+
+        if (getSchema().isUniqueConstraint()) {
+            setUniqueValue((PlainAttrUniqueValue) attrValue);
+        } else {
+            if (!getSchema().isMultivalue()) {
+                getValues().clear();
+            }
+            addValue(attrValue);
+        }
+    }
+
+    @Override
+    public List<String> getValuesAsStrings() {
+        List<String> result;
+        if (getUniqueValue() == null) {
+            result = new ArrayList<>(getValues().size());
+            for (PlainAttrValue attributeValue : getValues()) {
+                result.add(attributeValue.getValueAsString());
+            }
+        } else {
+            result = Collections.singletonList(getUniqueValue().getValueAsString());
+        }
+
+        return result;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractPlainAttrValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractPlainAttrValue.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractPlainAttrValue.java
new file mode 100644
index 0000000..282e3da
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/AbstractPlainAttrValue.java
@@ -0,0 +1,282 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import java.util.Date;
+import javax.persistence.Basic;
+import javax.persistence.Lob;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidPlainAttrValueException;
+import org.apache.syncope.persistence.api.attrvalue.validation.ParsingValidationException;
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.apache.syncope.server.utils.DataFormat;
+import org.apache.syncope.persistence.jpa.validation.entity.PlainAttrValueCheck;
+import org.apache.syncope.server.security.Encryptor;
+
+@MappedSuperclass
+@PlainAttrValueCheck
+public abstract class AbstractPlainAttrValue extends AbstractEntity<Long> implements PlainAttrValue {
+
+    private static final long serialVersionUID = -9141923816611244785L;
+
+    private String stringValue;
+
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date dateValue;
+
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer booleanValue;
+
+    private Long longValue;
+
+    private Double doubleValue;
+
+    @Lob
+    private byte[] binaryValue;
+
+    @Override
+    public Boolean getBooleanValue() {
+        return booleanValue == null
+                ? null
+                : isBooleanAsInteger(booleanValue);
+    }
+
+    @Override
+    public void setBooleanValue(final Boolean booleanValue) {
+        this.booleanValue = booleanValue == null
+                ? null
+                : getBooleanAsInteger(booleanValue);
+    }
+
+    @Override
+    public Date getDateValue() {
+        return dateValue == null
+                ? null
+                : new Date(dateValue.getTime());
+    }
+
+    @Override
+    public void setDateValue(final Date dateValue) {
+        this.dateValue = dateValue == null
+                ? null
+                : new Date(dateValue.getTime());
+    }
+
+    @Override
+    public Double getDoubleValue() {
+        return doubleValue;
+    }
+
+    @Override
+    public void setDoubleValue(final Double doubleValue) {
+        this.doubleValue = doubleValue;
+    }
+
+    @Override
+    public Long getLongValue() {
+        return longValue;
+    }
+
+    @Override
+    public void setLongValue(final Long longValue) {
+        this.longValue = longValue;
+    }
+
+    @Override
+    public String getStringValue() {
+        return stringValue;
+    }
+
+    @Override
+    public void setStringValue(final String stringValue) {
+        this.stringValue = stringValue;
+    }
+
+    @Override
+    public byte[] getBinaryValue() {
+        return binaryValue;
+    }
+
+    @Override
+    public void setBinaryValue(final byte[] binaryValue) {
+        this.binaryValue = ArrayUtils.clone(binaryValue);
+    }
+
+    @Override
+    public void parseValue(final PlainSchema schema, final String value) throws ParsingValidationException {
+        Exception exception = null;
+
+        switch (schema.getType()) {
+
+            case Boolean:
+                this.setBooleanValue(Boolean.parseBoolean(value));
+                break;
+
+            case Long:
+                try {
+                    this.setLongValue(schema.getConversionPattern() == null
+                            ? Long.valueOf(value)
+                            : DataFormat.parseNumber(value, schema.getConversionPattern()).longValue());
+                } catch (Exception pe) {
+                    exception = pe;
+                }
+                break;
+
+            case Double:
+                try {
+                    this.setDoubleValue(schema.getConversionPattern() == null
+                            ? Double.valueOf(value)
+                            : DataFormat.parseNumber(value, schema.getConversionPattern()).doubleValue());
+                } catch (Exception pe) {
+                    exception = pe;
+                }
+                break;
+
+            case Date:
+                try {
+                    this.setDateValue(schema.getConversionPattern() == null
+                            ? DataFormat.parseDate(value)
+                            : new Date(DataFormat.parseDate(value, schema.getConversionPattern()).getTime()));
+                } catch (Exception pe) {
+                    exception = pe;
+                }
+                break;
+
+            case Encrypted:
+                try {
+                    this.setStringValue(Encryptor.getInstance(schema.getSecretKey()).
+                            encode(value, schema.getCipherAlgorithm()));
+                } catch (Exception pe) {
+                    exception = pe;
+                }
+                break;
+
+            case Binary:
+                this.setBinaryValue(Base64.decodeBase64(value));
+                break;
+
+            case String:
+            case Enum:
+            default:
+                this.setStringValue(value);
+        }
+
+        if (exception != null) {
+            throw new ParsingValidationException("While trying to parse '" + value + "' as " + schema.getKey(),
+                    exception);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T getValue() {
+        return (T) (booleanValue != null
+                ? getBooleanValue()
+                : dateValue != null
+                        ? getDateValue()
+                        : doubleValue != null
+                                ? getDoubleValue()
+                                : longValue != null
+                                        ? getLongValue()
+                                        : binaryValue != null
+                                                ? getBinaryValue()
+                                                : stringValue);
+    }
+
+    @Override
+    public String getValueAsString() {
+        final AttrSchemaType type = getAttr() == null || getAttr().getSchema() == null
+                || getAttr().getSchema().getType() == null
+                        ? AttrSchemaType.String
+                        : getAttr().getSchema().getType();
+
+        return getValueAsString(type);
+    }
+
+    @Override
+    public String getValueAsString(final AttrSchemaType type) {
+        Exception exception = null;
+
+        String result = null;
+
+        switch (type) {
+
+            case Boolean:
+                result = getBooleanValue().toString();
+                break;
+
+            case Long:
+                result = getAttr() == null || getAttr().getSchema() == null
+                        || getAttr().getSchema().getConversionPattern() == null
+                                ? getLongValue().toString()
+                                : DataFormat.format(getLongValue(), getAttr().getSchema().getConversionPattern());
+                break;
+
+            case Double:
+                result = getAttr() == null || getAttr().getSchema() == null
+                        || getAttr().getSchema().getConversionPattern() == null
+                                ? getDoubleValue().toString()
+                                : DataFormat.format(getDoubleValue(), getAttr().getSchema().getConversionPattern());
+                break;
+
+            case Date:
+                result = getAttr() == null || getAttr().getSchema() == null
+                        || getAttr().getSchema().getConversionPattern() == null
+                                ? DataFormat.format(getDateValue())
+                                : DataFormat.format(getDateValue(), false, getAttr().getSchema().
+                                        getConversionPattern());
+                break;
+
+            case Binary:
+                result = new String(Base64.encodeBase64String(getBinaryValue()));
+                break;
+
+            case String:
+            case Enum:
+            case Encrypted:
+            default:
+                result = getStringValue();
+                break;
+        }
+
+        if (exception != null) {
+            throw new InvalidPlainAttrValueException(
+                    "While trying to format '" + getValue() + "' as " + type, exception);
+        }
+
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
+    }
+}


[32/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
[SYNCOPE-620] JPA entities + basic tests


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

Branch: refs/heads/2_0_X
Commit: 556d518625f25baee800203e6dd274aeb8e9f91b
Parents: 20390b0
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu Jan 1 19:11:28 2015 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Jan 1 19:11:28 2015 +0100

----------------------------------------------------------------------
 syncope620/common/lib/pom.xml                   |    6 +-
 .../syncope/common/lib/AbstractBaseBean.java    |   49 +
 .../syncope/common/lib/SyncopeConstants.java    |   52 +
 .../lib/annotation/FormAttributeField.java      |   36 +
 .../common/lib/mod/AbstractAttributableMod.java |  111 ++
 .../common/lib/mod/AbstractSubjectMod.java      |   56 +
 .../apache/syncope/common/lib/mod/AttrMod.java  |   76 ++
 .../lib/report/AbstractReportletConf.java       |   50 +
 .../common/lib/report/RoleReportletConf.java    |  109 ++
 .../common/lib/report/StaticReportletConf.java  |  107 ++
 .../common/lib/report/UserReportletConf.java    |  114 ++
 .../syncope/common/lib/report/package-info.java |   23 +
 .../common/lib/to/AbstractAnnotatedBean.java    |  108 ++
 .../common/lib/to/AbstractAttributableTO.java   |   86 ++
 .../common/lib/to/AbstractSubjectTO.java        |   68 ++
 .../apache/syncope/common/lib/to/AttrTO.java    |   92 ++
 .../syncope/common/lib/to/ConnObjectTO.java     |   58 +
 .../syncope/common/lib/to/ConnPoolConfTO.java   |   81 ++
 .../syncope/common/lib/to/MembershipTO.java     |   49 +
 .../common/lib/to/PropagationStatus.java        |  152 +++
 .../apache/syncope/common/lib/to/RoleTO.java    |  258 ++++
 .../apache/syncope/common/lib/to/UserTO.java    |  183 +++
 .../common/lib/types/EntityViolationType.java   |   63 +-
 .../lib/types/PropagationTaskExecStatus.java    |   47 +
 .../syncope/common/lib/types/TaskType.java      |   54 +
 syncope620/pom.xml                              |  206 ++++
 syncope620/server/persistence-api/pom.xml       |   10 +-
 .../persistence/api/RoleEntitlementUtil.java    |   88 ++
 .../validation/InvalidEntityException.java      |  129 ++
 .../InvalidPlainAttrValueException.java         |   43 +
 .../validation/ParsingValidationException.java  |   30 +
 .../api/attrvalue/validation/Validator.java     |   27 +
 .../api/content/ContentExporter.java            |   28 +
 .../persistence/api/content/ContentLoader.java  |   25 +
 .../persistence/api/dao/AttrTemplateDAO.java    |    4 +-
 .../syncope/persistence/api/dao/ConfDAO.java    |   10 +-
 .../persistence/api/dao/ConnInstanceDAO.java    |   34 +
 .../apache/syncope/persistence/api/dao/DAO.java |    6 +-
 .../syncope/persistence/api/dao/DerAttrDAO.java |   15 +-
 .../persistence/api/dao/DerSchemaDAO.java       |    7 +-
 .../persistence/api/dao/EntitlementDAO.java     |    6 +-
 .../api/dao/ExternalResourceDAO.java            |    4 +-
 .../syncope/persistence/api/dao/LoggerDAO.java  |    4 +-
 .../persistence/api/dao/MembershipDAO.java      |    4 +-
 .../persistence/api/dao/NormAttrDAO.java        |   30 -
 .../persistence/api/dao/NormAttrValueDAO.java   |   36 -
 .../persistence/api/dao/NormSchemaDAO.java      |   38 -
 .../persistence/api/dao/NotificationDAO.java    |    4 +-
 .../persistence/api/dao/PlainAttrDAO.java       |   30 +
 .../persistence/api/dao/PlainAttrValueDAO.java  |   36 +
 .../persistence/api/dao/PlainSchemaDAO.java     |   38 +
 .../syncope/persistence/api/dao/PolicyDAO.java  |    2 +-
 .../syncope/persistence/api/dao/ReportDAO.java  |    4 +-
 .../persistence/api/dao/ReportExecDAO.java      |    4 +-
 .../syncope/persistence/api/dao/RoleDAO.java    |   12 +-
 .../api/dao/SecurityQuestionDAO.java            |    4 +-
 .../syncope/persistence/api/dao/SubjectDAO.java |   20 +-
 .../persistence/api/dao/SubjectSearchDAO.java   |   17 +-
 .../syncope/persistence/api/dao/TaskDAO.java    |   23 +-
 .../persistence/api/dao/TaskExecDAO.java        |    7 +-
 .../syncope/persistence/api/dao/UserDAO.java    |   12 +-
 .../syncope/persistence/api/dao/VirAttrDAO.java |    4 +-
 .../persistence/api/dao/VirSchemaDAO.java       |    7 +-
 .../dao/validation/InvalidEntityException.java  |  129 --
 .../InvalidNormAttrValueException.java          |   43 -
 .../validation/ParsingValidationException.java  |   30 -
 .../api/dao/validation/Validator.java           |   26 -
 .../persistence/api/entity/AccountPolicy.java   |    9 +-
 .../syncope/persistence/api/entity/Attr.java    |    2 +-
 .../persistence/api/entity/AttrTemplate.java    |    6 +-
 .../persistence/api/entity/Attributable.java    |   26 +-
 .../api/entity/AttributableUtil.java            |   23 +-
 .../persistence/api/entity/ConnInstance.java    |    8 +-
 .../syncope/persistence/api/entity/DerAttr.java |    4 +-
 .../api/entity/ExternalResource.java            |    4 -
 .../syncope/persistence/api/entity/Logger.java  |    2 +-
 .../syncope/persistence/api/entity/Mapping.java |    4 +-
 .../persistence/api/entity/MappingItem.java     |    4 +-
 .../persistence/api/entity/NormAttr.java        |   37 -
 .../persistence/api/entity/NormAttrValue.java   |   62 -
 .../persistence/api/entity/NormSchema.java      |   56 -
 .../persistence/api/entity/Notification.java    |    6 -
 .../persistence/api/entity/PlainAttr.java       |   37 +
 .../api/entity/PlainAttrUniqueValue.java        |   26 +
 .../persistence/api/entity/PlainAttrValue.java  |   62 +
 .../persistence/api/entity/PlainSchema.java     |   67 ++
 .../persistence/api/entity/PushPolicy.java      |   23 +
 .../syncope/persistence/api/entity/Report.java  |    8 +-
 .../api/entity/ReportletConfInstance.java       |   33 +
 .../syncope/persistence/api/entity/Schema.java  |   12 +-
 .../syncope/persistence/api/entity/Subject.java |    6 +-
 .../syncope/persistence/api/entity/VirAttr.java |    2 -
 .../persistence/api/entity/VirSchema.java       |    1 +
 .../persistence/api/entity/conf/CNormAttr.java  |   25 -
 .../persistence/api/entity/conf/CPlainAttr.java |   39 +
 .../api/entity/conf/CPlainAttrUniqueValue.java  |   31 +
 .../api/entity/conf/CPlainAttrValue.java        |   28 +
 .../api/entity/conf/CPlainSchema.java           |   25 +
 .../persistence/api/entity/conf/Conf.java       |   12 +-
 .../api/entity/membership/MDerAttr.java         |    8 +-
 .../api/entity/membership/MDerAttrTemplate.java |    3 +-
 .../api/entity/membership/MDerSchema.java       |   25 +
 .../api/entity/membership/MNormAttr.java        |   28 -
 .../entity/membership/MNormAttrTemplate.java    |   26 -
 .../api/entity/membership/MNormAttrValue.java   |   25 -
 .../api/entity/membership/MPlainAttr.java       |   42 +
 .../entity/membership/MPlainAttrTemplate.java   |   25 +
 .../membership/MPlainAttrUniqueValue.java       |   31 +
 .../api/entity/membership/MPlainAttrValue.java  |   28 +
 .../api/entity/membership/MPlainSchema.java     |   25 +
 .../api/entity/membership/MVirAttr.java         |    6 +
 .../api/entity/membership/MVirAttrTemplate.java |    3 +-
 .../api/entity/membership/MVirSchema.java       |   25 +
 .../api/entity/membership/Membership.java       |   28 +-
 .../persistence/api/entity/role/RDerAttr.java   |    8 +-
 .../api/entity/role/RDerAttrTemplate.java       |    3 +-
 .../persistence/api/entity/role/RDerSchema.java |   25 +
 .../api/entity/role/RMappingItem.java           |    4 +
 .../persistence/api/entity/role/RNormAttr.java  |   28 -
 .../api/entity/role/RNormAttrTemplate.java      |   26 -
 .../api/entity/role/RNormAttrValue.java         |   25 -
 .../persistence/api/entity/role/RPlainAttr.java |   42 +
 .../api/entity/role/RPlainAttrTemplate.java     |   25 +
 .../api/entity/role/RPlainAttrUniqueValue.java  |   31 +
 .../api/entity/role/RPlainAttrValue.java        |   28 +
 .../api/entity/role/RPlainSchema.java           |   25 +
 .../persistence/api/entity/role/RVirAttr.java   |    6 +
 .../api/entity/role/RVirAttrTemplate.java       |    3 +-
 .../persistence/api/entity/role/RVirSchema.java |   25 +
 .../persistence/api/entity/role/Role.java       |   26 +-
 .../api/entity/task/NotificationTask.java       |    2 -
 .../persistence/api/entity/task/SyncTask.java   |   11 +-
 .../persistence/api/entity/task/Task.java       |    7 +-
 .../persistence/api/entity/user/UDerAttr.java   |    8 +-
 .../persistence/api/entity/user/UDerSchema.java |   25 +
 .../api/entity/user/UMappingItem.java           |    4 +
 .../persistence/api/entity/user/UNormAttr.java  |   25 -
 .../api/entity/user/UNormAttrValue.java         |   25 -
 .../persistence/api/entity/user/UPlainAttr.java |   38 +
 .../api/entity/user/UPlainAttrUniqueValue.java  |   31 +
 .../api/entity/user/UPlainAttrValue.java        |   28 +
 .../api/entity/user/UPlainSchema.java           |   25 +
 .../persistence/api/entity/user/UVirAttr.java   |    6 +
 .../persistence/api/entity/user/UVirSchema.java |   25 +
 .../persistence/api/entity/user/User.java       |   32 +-
 syncope620/server/persistence-jpa/pom.xml       |  224 ++++
 .../attrvalue/validation/AbstractValidator.java |   54 +
 .../validation/AlwaysTrueValidator.java         |   40 +
 .../attrvalue/validation/BasicValidator.java    |   54 +
 .../validation/EmailAddressValidator.java       |   42 +
 .../jpa/content/AbstractContentDealer.java      |   88 ++
 .../jpa/content/ContentLoaderHandler.java       |  199 ++++
 .../jpa/content/XMLContentLoader.java           |   89 ++
 .../persistence/jpa/dao/AbstractDAO.java        |  117 ++
 .../persistence/jpa/dao/AbstractSubjectDAO.java |  349 ++++++
 .../persistence/jpa/dao/JPAAttrTemplateDAO.java |  107 ++
 .../syncope/persistence/jpa/dao/JPAConfDAO.java |  106 ++
 .../persistence/jpa/dao/JPAConnInstanceDAO.java |   90 ++
 .../persistence/jpa/dao/JPADerAttrDAO.java      |   86 ++
 .../persistence/jpa/dao/JPADerSchemaDAO.java    |  132 ++
 .../persistence/jpa/dao/JPAEntitlementDAO.java  |   88 ++
 .../jpa/dao/JPAExternalResourceDAO.java         |  254 ++++
 .../persistence/jpa/dao/JPALoggerDAO.java       |   69 ++
 .../persistence/jpa/dao/JPAMembershipDAO.java   |   87 ++
 .../persistence/jpa/dao/JPANotificationDAO.java |   53 +
 .../persistence/jpa/dao/JPAPlainAttrDAO.java    |   76 ++
 .../jpa/dao/JPAPlainAttrValueDAO.java           |  104 ++
 .../persistence/jpa/dao/JPAPlainSchemaDAO.java  |  141 +++
 .../persistence/jpa/dao/JPAPolicyDAO.java       |  150 +++
 .../persistence/jpa/dao/JPAReportDAO.java       |   90 ++
 .../persistence/jpa/dao/JPAReportExecDAO.java   |  101 ++
 .../syncope/persistence/jpa/dao/JPARoleDAO.java |  531 +++++++++
 .../jpa/dao/JPASecurityQuestionDAO.java         |   71 ++
 .../jpa/dao/JPASubjectSearchDAO.java            |  715 +++++++++++
 .../syncope/persistence/jpa/dao/JPATaskDAO.java |  185 +++
 .../persistence/jpa/dao/JPATaskExecDAO.java     |  118 ++
 .../syncope/persistence/jpa/dao/JPAUserDAO.java |  225 ++++
 .../persistence/jpa/dao/JPAVirAttrDAO.java      |   86 ++
 .../persistence/jpa/dao/JPAVirSchemaDAO.java    |  131 ++
 .../persistence/jpa/dao/OrderBySupport.java     |   47 +
 .../persistence/jpa/dao/SearchSupport.java      |  132 ++
 .../jpa/entity/AbstractAnnotatedEntity.java     |  113 ++
 .../jpa/entity/AbstractAttrTemplate.java        |   42 +
 .../jpa/entity/AbstractAttributable.java        |  106 ++
 .../persistence/jpa/entity/AbstractDerAttr.java |   52 +
 .../jpa/entity/AbstractDerSchema.java           |   85 ++
 .../persistence/jpa/entity/AbstractEntity.java  |  112 ++
 .../persistence/jpa/entity/AbstractExec.java    |  114 ++
 .../persistence/jpa/entity/AbstractMapping.java |   76 ++
 .../jpa/entity/AbstractMappingItem.java         |  190 +++
 .../jpa/entity/AbstractPlainAttr.java           |   81 ++
 .../jpa/entity/AbstractPlainAttrValue.java      |  282 +++++
 .../jpa/entity/AbstractPlainSchema.java         |  271 +++++
 .../persistence/jpa/entity/AbstractSubject.java |   64 +
 .../persistence/jpa/entity/AbstractVirAttr.java |   62 +
 .../jpa/entity/AbstractVirSchema.java           |   89 ++
 .../jpa/entity/AnnotatedEntityListener.java     |   54 +
 .../jpa/entity/JPAAccountPolicy.java            |   90 ++
 .../jpa/entity/JPAAttributableUtil.java         |  882 ++++++++++++++
 .../persistence/jpa/entity/JPAConnInstance.java |  268 +++++
 .../persistence/jpa/entity/JPAConnPoolConf.java |  107 ++
 .../persistence/jpa/entity/JPAEntitlement.java  |   62 +
 .../jpa/entity/JPAExternalResource.java         |  426 +++++++
 .../persistence/jpa/entity/JPALogger.java       |   80 ++
 .../persistence/jpa/entity/JPANotification.java |  262 ++++
 .../jpa/entity/JPAPasswordPolicy.java           |   43 +
 .../persistence/jpa/entity/JPAPolicy.java       |   90 ++
 .../persistence/jpa/entity/JPAPushPolicy.java   |   42 +
 .../persistence/jpa/entity/JPAReport.java       |  150 +++
 .../persistence/jpa/entity/JPAReportExec.java   |   87 ++
 .../jpa/entity/JPAReportletConfInstance.java    |   77 ++
 .../jpa/entity/JPASecurityQuestion.java         |   56 +
 .../persistence/jpa/entity/JPASyncPolicy.java   |   43 +
 .../jpa/entity/conf/JPACPlainAttr.java          |  150 +++
 .../entity/conf/JPACPlainAttrUniqueValue.java   |   78 ++
 .../jpa/entity/conf/JPACPlainAttrValue.java     |   64 +
 .../jpa/entity/conf/JPACPlainSchema.java        |   36 +
 .../persistence/jpa/entity/conf/JPAConf.java    |  116 ++
 .../jpa/entity/membership/JPAMDerAttr.java      |   82 ++
 .../entity/membership/JPAMDerAttrTemplate.java  |   67 ++
 .../jpa/entity/membership/JPAMDerSchema.java    |   34 +
 .../jpa/entity/membership/JPAMPlainAttr.java    |  141 +++
 .../membership/JPAMPlainAttrTemplate.java       |   68 ++
 .../membership/JPAMPlainAttrUniqueValue.java    |   78 ++
 .../entity/membership/JPAMPlainAttrValue.java   |   64 +
 .../jpa/entity/membership/JPAMPlainSchema.java  |   36 +
 .../jpa/entity/membership/JPAMVirAttr.java      |   81 ++
 .../entity/membership/JPAMVirAttrTemplate.java  |   67 ++
 .../jpa/entity/membership/JPAMVirSchema.java    |   36 +
 .../jpa/entity/membership/JPAMembership.java    |  195 +++
 .../jpa/entity/role/JPARDerAttr.java            |   82 ++
 .../jpa/entity/role/JPARDerAttrTemplate.java    |   66 +
 .../jpa/entity/role/JPARDerSchema.java          |   34 +
 .../jpa/entity/role/JPARMapping.java            |  103 ++
 .../jpa/entity/role/JPARMappingItem.java        |   58 +
 .../jpa/entity/role/JPARPlainAttr.java          |  140 +++
 .../jpa/entity/role/JPARPlainAttrTemplate.java  |   66 +
 .../entity/role/JPARPlainAttrUniqueValue.java   |   78 ++
 .../jpa/entity/role/JPARPlainAttrValue.java     |   64 +
 .../jpa/entity/role/JPARPlainSchema.java        |   36 +
 .../jpa/entity/role/JPARVirAttr.java            |   82 ++
 .../jpa/entity/role/JPARVirAttrTemplate.java    |   66 +
 .../jpa/entity/role/JPARVirSchema.java          |   36 +
 .../persistence/jpa/entity/role/JPARole.java    |  593 +++++++++
 .../entity/task/AbstractProvisioningTask.java   |  168 +++
 .../jpa/entity/task/JPANotificationTask.java    |  160 +++
 .../jpa/entity/task/JPAPropagationTask.java     |  199 ++++
 .../jpa/entity/task/JPAPushTask.java            |   82 ++
 .../jpa/entity/task/JPASchedTask.java           |   89 ++
 .../jpa/entity/task/JPASyncTask.java            |  110 ++
 .../persistence/jpa/entity/task/JPATask.java    |   96 ++
 .../jpa/entity/task/JPATaskExec.java            |   82 ++
 .../jpa/entity/user/JPAUDerAttr.java            |   67 ++
 .../jpa/entity/user/JPAUDerSchema.java          |   34 +
 .../jpa/entity/user/JPAUMapping.java            |  125 ++
 .../jpa/entity/user/JPAUMappingItem.java        |   58 +
 .../jpa/entity/user/JPAUPlainAttr.java          |  147 +++
 .../entity/user/JPAUPlainAttrUniqueValue.java   |   79 ++
 .../jpa/entity/user/JPAUPlainAttrValue.java     |   64 +
 .../jpa/entity/user/JPAUPlainSchema.java        |   36 +
 .../jpa/entity/user/JPAUVirAttr.java            |   67 ++
 .../jpa/entity/user/JPAUVirSchema.java          |   36 +
 .../persistence/jpa/entity/user/JPAUser.java    |  536 +++++++++
 .../validation/entity/AbstractValidator.java    |   46 +
 .../validation/entity/ConnInstanceCheck.java    |   41 +
 .../entity/ConnInstanceValidator.java           |   64 +
 .../entity/EntityValidationListener.java        |   51 +
 .../entity/ExternalResourceCheck.java           |   41 +
 .../entity/ExternalResourceValidator.java       |  130 ++
 .../validation/entity/NotificationCheck.java    |   41 +
 .../entity/NotificationValidator.java           |   59 +
 .../jpa/validation/entity/PlainAttrCheck.java   |   41 +
 .../validation/entity/PlainAttrValidator.java   |   59 +
 .../validation/entity/PlainAttrValueCheck.java  |   41 +
 .../entity/PlainAttrValueValidator.java         |   98 ++
 .../jpa/validation/entity/PlainSchemaCheck.java |   41 +
 .../validation/entity/PlainSchemaValidator.java |   61 +
 .../jpa/validation/entity/PolicyCheck.java      |   41 +
 .../jpa/validation/entity/PolicyValidator.java  |   59 +
 .../validation/entity/PropagationTaskCheck.java |   41 +
 .../entity/PropagationTaskValidator.java        |   65 +
 .../entity/ProvisioningTaskCheck.java           |   41 +
 .../entity/ProvisioningTaskValidator.java       |   84 ++
 .../jpa/validation/entity/ReportCheck.java      |   41 +
 .../jpa/validation/entity/ReportValidator.java  |   67 ++
 .../jpa/validation/entity/RoleCheck.java        |   41 +
 .../jpa/validation/entity/RoleValidator.java    |   44 +
 .../jpa/validation/entity/SchedTaskCheck.java   |   41 +
 .../validation/entity/SchedTaskValidator.java   |   68 ++
 .../jpa/validation/entity/SchemaNameCheck.java  |   41 +
 .../validation/entity/SchemaNameValidator.java  |  133 +++
 .../jpa/validation/entity/UserCheck.java        |   42 +
 .../jpa/validation/entity/UserValidator.java    |  194 +++
 .../src/main/resources/META-INF/orm.xml         |  355 ++++++
 .../resources/META-INF/spring-persistence.xml   |   31 +
 .../src/main/resources/audit/audit.sql          |   24 +
 .../main/resources/audit/audit_mysql_innodb.sql |   24 +
 .../src/main/resources/audit/audit_oracle.sql   |   38 +
 .../main/resources/audit/audit_sqlserver.sql    |   28 +
 .../src/main/resources/content.xml              |  183 +++
 .../src/main/resources/indexes.xml              |   40 +
 .../src/main/resources/persistence.properties   |   27 +
 .../src/main/resources/persistenceContext.xml   |  136 +++
 .../resources/persistenceContextEMFactory.xml   |   56 +
 .../src/main/resources/quartz/tables_h2.sql     |  266 +++++
 .../src/main/resources/quartz/tables_mysql.sql  |  206 ++++
 .../resources/quartz/tables_mysql_innodb.sql    |  221 ++++
 .../src/main/resources/quartz/tables_oracle.sql |  208 ++++
 .../main/resources/quartz/tables_postgres.sql   |  204 ++++
 .../main/resources/quartz/tables_sqlServer.sql  |  296 +++++
 .../src/main/resources/views.xml                |  149 +++
 .../syncope/persistence/jpa/AbstractTest.java   |   28 +
 .../persistence/jpa/DummyConnectorRegistry.java |   37 +
 .../persistence/jpa/TestInitializer.java        |   37 +
 .../persistence/jpa/entity/AttrTest.java        |  237 ++++
 .../jpa/entity/AttributableSearchTest.java      |  484 ++++++++
 .../persistence/jpa/entity/ConfTest.java        |  109 ++
 .../jpa/entity/ConnInstanceTest.java            |  145 +++
 .../persistence/jpa/entity/DerAttrTest.java     |  280 +++++
 .../persistence/jpa/entity/DerSchemaTest.java   |  104 ++
 .../persistence/jpa/entity/EntitlementTest.java |   72 ++
 .../persistence/jpa/entity/MembershipTest.java  |   85 ++
 .../jpa/entity/NotificationTest.java            |  132 ++
 .../persistence/jpa/entity/PlainSchemaTest.java |  162 +++
 .../persistence/jpa/entity/PolicyTest.java      |  152 +++
 .../persistence/jpa/entity/ReportTest.java      |   83 ++
 .../persistence/jpa/entity/ResourceTest.java    |  268 +++++
 .../persistence/jpa/entity/RoleTest.java        |  143 +++
 .../jpa/entity/SecurityQuestionTest.java        |   68 ++
 .../persistence/jpa/entity/TaskExecTest.java    |   96 ++
 .../persistence/jpa/entity/TaskTest.java        |  118 ++
 .../persistence/jpa/entity/UserTest.java        |  213 ++++
 .../persistence/jpa/entity/VirAttrTest.java     |  145 +++
 .../persistence/jpa/entity/VirSchemaTest.java   |  103 ++
 .../jpa/relationship/EntitlementTest.java       |   57 +
 .../src/test/resources/content.xml              | 1125 ++++++++++++++++++
 .../src/test/resources/persistence.properties   |   28 +
 .../src/test/resources/persistenceTestEnv.xml   |   49 +
 .../src/test/resources/simplelogger.properties  |   17 +
 syncope620/server/pom.xml                       |    6 +-
 syncope620/server/provisioning-api/pom.xml      |   54 +
 .../provisioning/api/ConnPoolConfUtil.java      |   69 ++
 .../syncope/provisioning/api/Connector.java     |  216 ++++
 .../provisioning/api/ConnectorFactory.java      |   63 +
 .../provisioning/api/ConnectorRegistry.java     |   41 +
 .../provisioning/api/job/ProvisioningJob.java   |   28 +
 .../syncope/provisioning/api/job/PushJob.java   |   26 +
 .../syncope/provisioning/api/job/SyncJob.java   |   26 +
 .../syncope/provisioning/api/job/TaskJob.java   |   43 +
 .../api/propagation/PropagationActions.java     |   30 +
 .../api/sync/ProvisioningActions.java           |   42 +
 .../provisioning/api/sync/PushActions.java      |  137 +++
 .../provisioning/api/sync/SyncActions.java      |  175 +++
 .../provisioning/api/sync/SyncProfile.java      |   84 ++
 .../provisioning/api/sync/SyncResult.java       |  140 +++
 .../api/sync/SyncopeResultHandler.java          |   29 +
 syncope620/server/security/pom.xml              |   76 ++
 .../server/security/AuthContextUtil.java        |   55 +
 .../syncope/server/security/Encryptor.java      |  256 ++++
 .../server/security/SecureRandomUtil.java       |   44 +
 .../src/main/resources/security.properties      |   30 +
 syncope620/server/spring/pom.xml                |   48 +
 .../spring/ApplicationContextProvider.java      |   47 +
 .../apache/syncope/server/spring/BeanUtils.java |  201 ++++
 .../spring/ResourceWithFallbackLoader.java      |   82 ++
 syncope620/server/utils/pom.xml                 |   75 ++
 .../apache/syncope/server/utils/DataFormat.java |  117 ++
 .../apache/syncope/server/utils/URIUtil.java    |   61 +
 .../utils/jexl/ClassFreeUberspectImpl.java      |   43 +
 .../server/utils/jexl/EmptyClassLoader.java     |   36 +
 .../syncope/server/utils/jexl/JexlUtil.java     |  289 +++++
 .../utils/policy/AccountPolicyEnforcer.java     |  101 ++
 .../utils/policy/AccountPolicyException.java    |   32 +
 .../utils/policy/PasswordPolicyEnforcer.java    |  202 ++++
 .../utils/policy/PasswordPolicyException.java   |   32 +
 .../utils/policy/PolicyEnforceException.java    |   32 +
 .../server/utils/policy/PolicyEnforcer.java     |   30 +
 .../server/utils/policy/PolicyEvaluator.java    |  109 ++
 .../server/utils/policy/PolicyException.java    |   32 +
 .../server/utils/policy/PolicyPattern.java      |   50 +
 .../server/utils/policy/UserSuspender.java      |   26 +
 .../serialization/AttributeDeserializer.java    |   84 ++
 .../serialization/AttributeSerializer.java      |   78 ++
 .../GuardedStringDeserializer.java              |   94 ++
 .../serialization/GuardedStringSerializer.java  |   90 ++
 .../server/utils/serialization/POJOHelper.java  |   80 ++
 .../serialization/SyncTokenDeserializer.java    |   65 +
 .../serialization/SyncTokenSerializer.java      |   58 +
 388 files changed, 31675 insertions(+), 1000 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/pom.xml
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/pom.xml b/syncope620/common/lib/pom.xml
index 4c9cccc..d52f136 100644
--- a/syncope620/common/lib/pom.xml
+++ b/syncope620/common/lib/pom.xml
@@ -30,7 +30,7 @@ under the License.
   <name>Apache Syncope Common Lib</name>
   <description>Apache Syncope Common Lib</description>
   <groupId>org.apache.syncope.common</groupId>
-  <artifactId>syncope-lib</artifactId>
+  <artifactId>syncope-common-lib</artifactId>
   <packaging>jar</packaging>
 
   <dependencies>
@@ -45,6 +45,10 @@ under the License.
     </dependency>
     
     <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-api</artifactId>
     </dependency>

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/AbstractBaseBean.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/AbstractBaseBean.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/AbstractBaseBean.java
new file mode 100644
index 0000000..28bd4bd
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/AbstractBaseBean.java
@@ -0,0 +1,49 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+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
+// Reporting here only classes used via PagedResult
+//@XmlSeeAlso({ AbstractTaskTO.class, ReportTO.class, RoleTO.class, UserTO.class })
+public abstract class AbstractBaseBean implements Serializable {
+
+    private static final long serialVersionUID = 3119542005279892164L;
+
+    @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/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java
new file mode 100644
index 0000000..817b00d
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java
@@ -0,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;
+
+import java.util.regex.Pattern;
+
+public class SyncopeConstants {
+
+    public static final String NAMESPACE = "http://syncope.apache.org/2.0";
+
+    public static final String UNAUTHENTICATED = "unauthenticated";
+
+    public static final String ANONYMOUS_ENTITLEMENT = "anonymous";
+
+    public static final String ENUM_VALUES_SEPARATOR = ";";
+
+    public static final String[] DATE_PATTERNS = {
+        "yyyy-MM-dd'T'HH:mm:ssZ",
+        "EEE, dd MMM yyyy HH:mm:ss z",
+        "yyyy-MM-dd'T'HH:mm:ssz",
+        "yyyy-MM-dd HH:mm:ss",
+        "yyyy-MM-dd HH:mm:ss.S", // explicitly added to import date into MySql repository
+        "yyyy-MM-dd" };
+
+    public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ssZ";
+
+    public static final String DEFAULT_ENCODING = "UTF-8";
+
+    public static final String ROOT_LOGGER = "ROOT";
+
+    public static final Pattern EMAIL_PATTERN = Pattern.compile(
+            "^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*"
+            + "@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$",
+            Pattern.CASE_INSENSITIVE);
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/FormAttributeField.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/FormAttributeField.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/FormAttributeField.java
new file mode 100644
index 0000000..f007020
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/annotation/FormAttributeField.java
@@ -0,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.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 roleSearch() default false;
+
+    IntMappingType schema() default IntMappingType.UserSchema;
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AbstractAttributableMod.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AbstractAttributableMod.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AbstractAttributableMod.java
new file mode 100644
index 0000000..7339565
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AbstractAttributableMod.java
@@ -0,0 +1,111 @@
+/*
+ * 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.mod;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.HashSet;
+import java.util.Set;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+
+/**
+ * Abstract base class for objects that can have attributes removed, added or updated.
+ *
+ * Attributes can be regular attributes, derived attributes, virtual attributes and resources.
+ */
+@XmlType
+public abstract class AbstractAttributableMod extends AbstractBaseBean {
+
+    private static final long serialVersionUID = 3241118574016303198L;
+
+    protected long key;
+
+    protected final Set<AttrMod> attrsToUpdate = new HashSet<>();
+
+    protected final Set<String> attrsToRemove = new HashSet<>();
+
+    protected final Set<String> derAttrsToAdd = new HashSet<>();
+
+    protected final Set<String> derAttrsToRemove = new HashSet<>();
+
+    protected final Set<AttrMod> virAttrsToUpdate = new HashSet<>();
+
+    protected final Set<String> virAttrsToRemove = new HashSet<>();
+
+    public long getKey() {
+        return key;
+    }
+
+    public void setKey(final long key) {
+        this.key = key;
+    }
+
+    @XmlElementWrapper(name = "attributesToRemove")
+    @XmlElement(name = "attribute")
+    @JsonProperty("attributesToRemove")
+    public Set<String> getAttrsToRemove() {
+        return attrsToRemove;
+    }
+
+    @XmlElementWrapper(name = "attributesToUpdate")
+    @XmlElement(name = "attributeMod")
+    @JsonProperty("attributesToUpdate")
+    public Set<AttrMod> getAttrsToUpdate() {
+        return attrsToUpdate;
+    }
+
+    @XmlElementWrapper(name = "derAttrsToAdd")
+    @XmlElement(name = "attribute")
+    @JsonProperty("derAttrsToAdd")
+    public Set<String> getDerAttrsToAdd() {
+        return derAttrsToAdd;
+    }
+
+    @XmlElementWrapper(name = "derAttrsToRemove")
+    @XmlElement(name = "attribute")
+    @JsonProperty("derAttrsToRemove")
+    public Set<String> getDerAttrsToRemove() {
+        return derAttrsToRemove;
+    }
+
+    @XmlElementWrapper(name = "virAttrsToRemove")
+    @XmlElement(name = "attribute")
+    @JsonProperty("virAttrsToRemove")
+    public Set<String> getVirAttrsToRemove() {
+        return virAttrsToRemove;
+    }
+
+    @XmlElementWrapper(name = "virAttrsToUpdate")
+    @XmlElement(name = "attribute")
+    @JsonProperty("virAttrsToUpdate")
+    public Set<AttrMod> getVirAttrsToUpdate() {
+        return virAttrsToUpdate;
+    }
+
+    /**
+     * @return true is all backing Sets are empty.
+     */
+    public boolean isEmpty() {
+        return attrsToUpdate.isEmpty() && attrsToRemove.isEmpty()
+                && derAttrsToAdd.isEmpty() && derAttrsToRemove.isEmpty()
+                && virAttrsToUpdate.isEmpty() && virAttrsToRemove.isEmpty();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AbstractSubjectMod.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AbstractSubjectMod.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AbstractSubjectMod.java
new file mode 100644
index 0000000..96e2a64
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AbstractSubjectMod.java
@@ -0,0 +1,56 @@
+/*
+ * 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.mod;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.HashSet;
+import java.util.Set;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType
+public abstract class AbstractSubjectMod extends AbstractAttributableMod {
+
+    private static final long serialVersionUID = -6404459635536484024L;
+
+    protected final Set<String> resourcesToAdd = new HashSet<>();
+
+    protected final Set<String> resourcesToRemove = new HashSet<>();
+
+    @XmlElementWrapper(name = "resourcesToAdd")
+    @XmlElement(name = "resource")
+    @JsonProperty("resourcesToAdd")
+    public Set<String> getResourcesToAdd() {
+        return resourcesToAdd;
+    }
+
+    @XmlElementWrapper(name = "resourcesToRemove")
+    @XmlElement(name = "resource")
+    @JsonProperty("resourcesToRemove")
+    public Set<String> getResourcesToRemove() {
+        return resourcesToRemove;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return super.isEmpty() && resourcesToAdd.isEmpty() && resourcesToRemove.isEmpty();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AttrMod.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AttrMod.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AttrMod.java
new file mode 100644
index 0000000..b0cee5b
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AttrMod.java
@@ -0,0 +1,76 @@
+/*
+ * 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.mod;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+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.AbstractBaseBean;
+
+@XmlRootElement
+@XmlType
+public class AttrMod extends AbstractBaseBean {
+
+    private static final long serialVersionUID = -913573979137431406L;
+
+    private String schema;
+
+    private List<String> valuesToBeAdded;
+
+    private List<String> valuesToBeRemoved;
+
+    public AttrMod() {
+        super();
+
+        valuesToBeAdded = new ArrayList<>();
+        valuesToBeRemoved = new ArrayList<>();
+    }
+
+    public String getSchema() {
+        return schema;
+    }
+
+    public void setSchema(final String schema) {
+        this.schema = schema;
+    }
+
+    @XmlElementWrapper(name = "valuesToBeAdded")
+    @XmlElement(name = "value")
+    @JsonProperty("valuesToBeAdded")
+    public List<String> getValuesToBeAdded() {
+        return valuesToBeAdded;
+    }
+
+    @XmlElementWrapper(name = "valuesToBeRemoved")
+    @XmlElement(name = "value")
+    @JsonProperty("valuesToBeRemoved")
+    public List<String> getValuesToBeRemoved() {
+        return valuesToBeRemoved;
+    }
+
+    @JsonIgnore
+    public boolean isEmpty() {
+        return valuesToBeAdded.isEmpty() && valuesToBeRemoved.isEmpty();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/AbstractReportletConf.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/AbstractReportletConf.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/AbstractReportletConf.java
new file mode 100644
index 0000000..6efdb32
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/AbstractReportletConf.java
@@ -0,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.common.lib.report;
+
+import javax.xml.bind.annotation.XmlSeeAlso;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+
+@XmlType
+@XmlSeeAlso({ StaticReportletConf.class, UserReportletConf.class, RoleReportletConf.class })
+public abstract class AbstractReportletConf extends AbstractBaseBean implements ReportletConf {
+
+    private static final long serialVersionUID = -6130008602014516608L;
+
+    private String name;
+
+    public AbstractReportletConf() {
+        this("");
+        setName(getClass().getName());
+    }
+
+    public AbstractReportletConf(final String name) {
+        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/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/RoleReportletConf.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/RoleReportletConf.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/RoleReportletConf.java
new file mode 100644
index 0000000..55e2da9
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/RoleReportletConf.java
@@ -0,0 +1,109 @@
+/*
+ * 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 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.XmlEnum;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.annotation.FormAttributeField;
+import org.apache.syncope.common.lib.types.IntMappingType;
+
+@XmlRootElement(name = "roleReportletConf")
+@XmlType
+public class RoleReportletConf extends AbstractReportletConf {
+
+    private static final long serialVersionUID = -8488503068032439699L;
+
+    @XmlEnum
+    @XmlType(name = "roleReportletConfFeature")
+    public enum Feature {
+
+        id,
+        name,
+        roleOwner,
+        userOwner,
+        entitlements,
+        users,
+        resources
+
+    }
+
+    @FormAttributeField(userSearch = true)
+    private String matchingCond;
+
+    @FormAttributeField(schema = IntMappingType.RoleSchema)
+    private final List<String> attrs = new ArrayList<String>();
+
+    @FormAttributeField(schema = IntMappingType.RoleDerivedSchema)
+    private final List<String> derAttrs = new ArrayList<String>();
+
+    @FormAttributeField(schema = IntMappingType.RoleVirtualSchema)
+    private final List<String> virAttrs = new ArrayList<String>();
+
+    private final List<Feature> features = new ArrayList<Feature>();
+
+    public RoleReportletConf() {
+        super();
+    }
+
+    public RoleReportletConf(final String name) {
+        super(name);
+    }
+
+    @XmlElementWrapper(name = "attributes")
+    @XmlElement(name = "attribute")
+    @JsonProperty("attributes")
+    public List<String> getAttrs() {
+        return attrs;
+    }
+
+    @XmlElementWrapper(name = "derivedAttributes")
+    @XmlElement(name = "attribute")
+    @JsonProperty("derivedAttributes")
+    public List<String> getDerAttrs() {
+        return derAttrs;
+    }
+
+    @XmlElementWrapper(name = "virtualAttributes")
+    @XmlElement(name = "attribute")
+    @JsonProperty("virtualAttributes")
+    public List<String> getVirAttrs() {
+        return virAttrs;
+    }
+
+    @XmlElementWrapper(name = "features")
+    @XmlElement(name = "feature")
+    @JsonProperty("features")
+    public List<Feature> getFeatures() {
+        return features;
+    }
+
+    public String getMatchingCond() {
+        return matchingCond;
+    }
+
+    public void setMatchingCond(final String matchingCond) {
+        this.matchingCond = matchingCond;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/StaticReportletConf.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/StaticReportletConf.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/StaticReportletConf.java
new file mode 100644
index 0000000..9160089
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/StaticReportletConf.java
@@ -0,0 +1,107 @@
+/*
+ * 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 com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.Date;
+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.TraceLevel;
+
+@XmlRootElement(name = "staticReportletConf")
+@XmlType
+public class StaticReportletConf extends AbstractReportletConf {
+
+    private static final long serialVersionUID = -4814950086361753689L;
+
+    private String stringField;
+
+    private Long longField;
+
+    private Double doubleField;
+
+    private Date dateField;
+
+    private TraceLevel traceLevel;
+
+    private final List<String> listField = new ArrayList<String>();
+
+    public StaticReportletConf() {
+        super();
+    }
+
+    public StaticReportletConf(final String name) {
+        super(name);
+    }
+
+    public Date getDateField() {
+        return dateField == null
+                ? null
+                : new Date(dateField.getTime());
+    }
+
+    public void setDateField(Date dateField) {
+        this.dateField = dateField == null
+                ? null
+                : new Date(dateField.getTime());
+    }
+
+    public Double getDoubleField() {
+        return doubleField;
+    }
+
+    public void setDoubleField(Double doubleField) {
+        this.doubleField = doubleField;
+    }
+
+    @XmlElementWrapper(name = "listField")
+    @XmlElement(name = "field")
+    @JsonProperty("listField")
+    public List<String> getListField() {
+        return listField;
+    }
+
+    public Long getLongField() {
+        return longField;
+    }
+
+    public void setLongField(Long longField) {
+        this.longField = longField;
+    }
+
+    public String getStringField() {
+        return stringField;
+    }
+
+    public void setStringField(String stringField) {
+        this.stringField = stringField;
+    }
+
+    public TraceLevel getTraceLevel() {
+        return traceLevel;
+    }
+
+    public void setTraceLevel(TraceLevel traceLevel) {
+        this.traceLevel = traceLevel;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/UserReportletConf.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/UserReportletConf.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/UserReportletConf.java
new file mode 100644
index 0000000..2c6ed17
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/UserReportletConf.java
@@ -0,0 +1,114 @@
+/*
+ * 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 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.XmlEnum;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.annotation.FormAttributeField;
+import org.apache.syncope.common.lib.types.IntMappingType;
+
+@XmlRootElement(name = "userReportletConf")
+@XmlType
+public class UserReportletConf extends AbstractReportletConf {
+
+    @XmlEnum
+    @XmlType(name = "userReportletConfFeature")
+    public enum Feature {
+
+        id,
+        username,
+        workflowId,
+        status,
+        creationDate,
+        lastLoginDate,
+        changePwdDate,
+        passwordHistorySize,
+        failedLoginCount,
+        memberships,
+        resources
+
+    }
+
+    private static final long serialVersionUID = 6602717600064602764L;
+
+    @FormAttributeField(userSearch = true)
+    private String matchingCond;
+
+    @FormAttributeField(schema = IntMappingType.UserSchema)
+    private final List<String> attrs = new ArrayList<String>();
+
+    @FormAttributeField(schema = IntMappingType.UserDerivedSchema)
+    private final List<String> derAttrs = new ArrayList<String>();
+
+    @FormAttributeField(schema = IntMappingType.UserVirtualSchema)
+    private final List<String> virAttrs = new ArrayList<String>();
+
+    private final List<Feature> features = new ArrayList<Feature>();
+
+    public UserReportletConf() {
+        super();
+    }
+
+    public UserReportletConf(final String name) {
+        super(name);
+    }
+
+    @XmlElementWrapper(name = "attributes")
+    @XmlElement(name = "attribute")
+    @JsonProperty("attributes")
+    public List<String> getAttrs() {
+        return attrs;
+    }
+
+    @XmlElementWrapper(name = "derivedAttributes")
+    @XmlElement(name = "attribute")
+    @JsonProperty("derivedAttributes")
+    public List<String> getDerAttrs() {
+        return derAttrs;
+    }
+
+    @XmlElementWrapper(name = "virtualAttributes")
+    @XmlElement(name = "attribute")
+    @JsonProperty("virtualAttributes")
+    public List<String> getVirAttrs() {
+        return virAttrs;
+    }
+
+    @XmlElementWrapper(name = "features")
+    @XmlElement(name = "feature")
+    @JsonProperty("features")
+    public List<Feature> getFeatures() {
+        return features;
+    }
+
+    public String getMatchingCond() {
+        return matchingCond;
+    }
+
+    public void setMatchingCond(final String matchingCond) {
+        this.matchingCond = matchingCond;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/package-info.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/package-info.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/package-info.java
new file mode 100644
index 0000000..bc452c1
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/report/package-info.java
@@ -0,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.
+ */
+@XmlSchema(namespace = SyncopeConstants.NAMESPACE)
+package org.apache.syncope.common.lib.report;
+
+import javax.xml.bind.annotation.XmlSchema;
+import org.apache.syncope.common.lib.SyncopeConstants;

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractAnnotatedBean.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractAnnotatedBean.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractAnnotatedBean.java
new file mode 100644
index 0000000..c0f7155
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractAnnotatedBean.java
@@ -0,0 +1,108 @@
+/*
+ * 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 org.apache.syncope.common.lib.AbstractBaseBean;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import java.util.Date;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Abstract wrapper for common system information.
+ */
+@XmlType
+public class AbstractAnnotatedBean extends AbstractBaseBean {
+
+    private static final long serialVersionUID = -930797879027642457L;
+
+    /**
+     * Username of the user that has created this profile.
+     * <p>
+     * Cannot be used a reference to an existing user for two main reasons: the creator can be the user <tt>admin</tt>;
+     * the creator could have been removed.
+     */
+    private String creator;
+
+    /**
+     * Creation date.
+     */
+    private Date creationDate;
+
+    /**
+     * Username of the user that has performed the last modification to this profile.
+     * <p>
+     * This field cannot be null: at creation time it have to be initialized with the creator username.
+     * <p>
+     * The modifier can be the user itself whether the last performed change has been a self-modification.
+     * <p>
+     * Cannot be used a reference to an existing user for two main reasons: the modifier can be the user <tt>admin</tt>;
+     * the modifier could have been removed.
+     */
+    private String lastModifier;
+
+    /**
+     * Last change date.
+     * <p>
+     * This field cannot be null: at creation time it has to be initialized with <tt>creationDate</tt> field value.
+     */
+    private Date lastChangeDate;
+
+    public String getCreator() {
+        return creator;
+    }
+
+    public void setCreator(final String creator) {
+        this.creator = creator;
+    }
+
+    public Date getCreationDate() {
+        return creationDate;
+    }
+
+    public void setCreationDate(final Date creationDate) {
+        this.creationDate = creationDate;
+    }
+
+    public String getLastModifier() {
+        return lastModifier;
+    }
+
+    public void setLastModifier(final String lastModifier) {
+        this.lastModifier = lastModifier;
+    }
+
+    public Date getLastChangeDate() {
+        return lastChangeDate;
+    }
+
+    public void setLastChangeDate(final Date lastChangeDate) {
+        this.lastChangeDate = lastChangeDate;
+    }
+
+    @JsonIgnore
+    public String getETagValue() {
+        Date etagDate = getLastChangeDate() == null
+                ? getCreationDate() : getLastChangeDate();
+        return etagDate == null
+                ? StringUtils.EMPTY
+                : String.valueOf(etagDate.getTime());
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractAttributableTO.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractAttributableTO.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractAttributableTO.java
new file mode 100644
index 0000000..5cb48bb
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractAttributableTO.java
@@ -0,0 +1,86 @@
+/*
+ * 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.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType
+public abstract class AbstractAttributableTO extends ConnObjectTO {
+
+    private static final long serialVersionUID = 4083884098736820255L;
+
+    private long id;
+
+    private final List<AttrTO> derAttrs = new ArrayList<>();
+
+    private final List<AttrTO> virAttrs = new ArrayList<>();
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(final long id) {
+        this.id = id;
+    }
+
+    @JsonIgnore
+    public Map<String, AttrTO> getDerAttrMap() {
+        Map<String, AttrTO> result = new HashMap<>(derAttrs.size());
+        for (AttrTO attributeTO : derAttrs) {
+            result.put(attributeTO.getSchema(), attributeTO);
+        }
+        result = Collections.unmodifiableMap(result);
+
+        return result;
+    }
+
+    @JsonIgnore
+    public Map<String, AttrTO> getVirAttrMap() {
+        Map<String, AttrTO> result = new HashMap<>(virAttrs.size());
+        for (AttrTO attributeTO : virAttrs) {
+            result.put(attributeTO.getSchema(), attributeTO);
+        }
+        result = Collections.unmodifiableMap(result);
+
+        return result;
+    }
+
+    @XmlElementWrapper(name = "derivedAttributes")
+    @XmlElement(name = "attribute")
+    @JsonProperty("derivedAttributes")
+    public List<AttrTO> getDerAttrs() {
+        return derAttrs;
+    }
+
+    @XmlElementWrapper(name = "virtualAttributes")
+    @XmlElement(name = "attribute")
+    @JsonProperty("virtualAttributes")
+    public List<AttrTO> getVirAttrs() {
+        return virAttrs;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractSubjectTO.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractSubjectTO.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractSubjectTO.java
new file mode 100644
index 0000000..5c9fa42
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractSubjectTO.java
@@ -0,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.to;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType
+public abstract class AbstractSubjectTO extends AbstractAttributableTO {
+
+    private static final long serialVersionUID = 114668706977919206L;
+
+    private final Set<String> resources = new HashSet<>();
+
+    private final List<PropagationStatus> propagationStatusTOs = new ArrayList<>();
+
+    @XmlElementWrapper(name = "resources")
+    @XmlElement(name = "resource")
+    @JsonProperty("resources")
+    public Set<String> getResources() {
+        return resources;
+    }
+
+    public boolean removePropagationTO(final String resource) {
+        if (resource != null && getPropagationStatusTOs().isEmpty()) {
+            final List<PropagationStatus> toBeRemoved = new ArrayList<PropagationStatus>();
+
+            for (PropagationStatus propagationTO : getPropagationStatusTOs()) {
+                if (resource.equals(propagationTO.getResource())) {
+                    toBeRemoved.add(propagationTO);
+                }
+            }
+
+            return propagationStatusTOs.removeAll(toBeRemoved);
+        }
+        return false;
+    }
+
+    @XmlElementWrapper(name = "propagationStatuses")
+    @XmlElement(name = "propagationStatus")
+    @JsonProperty("propagationStatuses")
+    public List<PropagationStatus> getPropagationStatusTOs() {
+        return propagationStatusTOs;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttrTO.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttrTO.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttrTO.java
new file mode 100644
index 0000000..829f309
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttrTO.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.to;
+
+import org.apache.syncope.common.lib.AbstractBaseBean;
+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 = "attribute")
+@XmlType
+public class AttrTO extends AbstractBaseBean {
+
+    private static final long serialVersionUID = 4941691338796323623L;
+
+    /**
+     * Name of the schema that this attribute is referring to.
+     */
+    private String schema;
+
+    /**
+     * Set of (string) values of this attribute.
+     */
+    private final List<String> values;
+
+    /**
+     * Whether this attribute is read-only or not.
+     */
+    private boolean readonly;
+
+    /**
+     * Default constructor.
+     */
+    public AttrTO() {
+        super();
+        values = new ArrayList<String>();
+        readonly = false;
+    }
+
+    /**
+     * @return the name of the schema that this attribute is referring to
+     */
+    public String getSchema() {
+        return schema;
+    }
+
+    /**
+     * @param schema name to be set
+     */
+    public void setSchema(final String schema) {
+        this.schema = schema;
+
+    }
+
+    /**
+     * @return attribute values as strings
+     */
+    @XmlElementWrapper(name = "values")
+    @XmlElement(name = "value")
+    @JsonProperty("values")
+    public List<String> getValues() {
+        return values;
+    }
+
+    public boolean isReadonly() {
+        return readonly;
+    }
+
+    public void setReadonly(final boolean readonly) {
+        this.readonly = readonly;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java
new file mode 100644
index 0000000..d298609
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java
@@ -0,0 +1,58 @@
+/*
+ * 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.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+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 = "connObject")
+@XmlType
+public class ConnObjectTO extends AbstractAnnotatedBean {
+
+    private static final long serialVersionUID = 5139554911265442497L;
+
+    private final List<AttrTO> attrs = new ArrayList<>();
+
+    @XmlElementWrapper(name = "attributes")
+    @XmlElement(name = "attribute")
+    @JsonProperty("attributes")
+    public List<AttrTO> getPlainAttrs() {
+        return attrs;
+    }
+
+    @JsonIgnore
+    public Map<String, AttrTO> getAttrMap() {
+        Map<String, AttrTO> result = new HashMap<>(attrs.size());
+        for (AttrTO attributeTO : attrs) {
+            result.put(attributeTO.getSchema(), attributeTO);
+        }
+        result = Collections.<String, AttrTO>unmodifiableMap(result);
+
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnPoolConfTO.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnPoolConfTO.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnPoolConfTO.java
new file mode 100644
index 0000000..9f455dc
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnPoolConfTO.java
@@ -0,0 +1,81 @@
+/*
+ * 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 org.apache.syncope.common.lib.AbstractBaseBean;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlRootElement(name = "connPoolConf")
+@XmlType
+public class ConnPoolConfTO extends AbstractBaseBean {
+
+    private static final long serialVersionUID = -214360178113476623L;
+
+    private Integer maxObjects;
+
+    private Integer minIdle;
+
+    private Integer maxIdle;
+
+    private Long maxWait;
+
+    private Long minEvictableIdleTimeMillis;
+
+    public Integer getMaxObjects() {
+        return maxObjects;
+    }
+
+    public void setMaxObjects(final Integer maxObjects) {
+        this.maxObjects = maxObjects;
+    }
+
+    public Integer getMinIdle() {
+        return minIdle;
+    }
+
+    public void setMinIdle(final Integer minIdle) {
+        this.minIdle = minIdle;
+    }
+
+    public Integer getMaxIdle() {
+        return maxIdle;
+    }
+
+    public void setMaxIdle(final Integer maxIdle) {
+        this.maxIdle = maxIdle;
+    }
+
+    public Long getMaxWait() {
+        return maxWait;
+    }
+
+    public void setMaxWait(final Long maxWait) {
+        this.maxWait = maxWait;
+    }
+
+    public Long getMinEvictableIdleTimeMillis() {
+        return minEvictableIdleTimeMillis;
+    }
+
+    public void setMinEvictableIdleTimeMillis(final Long minEvictableIdleTimeMillis) {
+        this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
new file mode 100644
index 0000000..d53e20a
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
@@ -0,0 +1,49 @@
+/*
+ * 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;
+
+@XmlRootElement(name = "membership")
+@XmlType
+public class MembershipTO extends AbstractAttributableTO {
+
+    private static final long serialVersionUID = 5992828670273935861L;
+
+    private long roleId;
+
+    private String roleName;
+
+    public long getRoleId() {
+        return roleId;
+    }
+
+    public void setRoleId(final long roleId) {
+        this.roleId = roleId;
+    }
+
+    public String getRoleName() {
+        return roleName;
+    }
+
+    public void setRoleName(final String roleName) {
+        this.roleName = roleName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/PropagationStatus.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/PropagationStatus.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/PropagationStatus.java
new file mode 100644
index 0000000..de844be
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/PropagationStatus.java
@@ -0,0 +1,152 @@
+/*
+ * 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 org.apache.syncope.common.lib.AbstractBaseBean;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
+
+/**
+ * Single propagation status.
+ */
+@XmlRootElement(name = "propagationStatus")
+@XmlType
+public class PropagationStatus extends AbstractBaseBean {
+
+    /**
+     * Serial version ID.
+     */
+    private static final long serialVersionUID = 3921498450222857690L;
+
+    /**
+     * Object before propagation.
+     */
+    private ConnObjectTO beforeObj;
+
+    /**
+     * Object after propagation.
+     */
+    private ConnObjectTO afterObj;
+
+    /**
+     * Propagated resource name.
+     */
+    private String resource;
+
+    /**
+     * Propagation task execution status.
+     */
+    private PropagationTaskExecStatus status;
+
+    /**
+     * Propagation task execution failure message.
+     */
+    private String failureReason;
+
+    /**
+     * After object getter.
+     *
+     * @return after object.
+     */
+    public ConnObjectTO getAfterObj() {
+        return afterObj;
+    }
+
+    /**
+     * After object setter.
+     *
+     * @param afterObj object.
+     */
+    public void setAfterObj(final ConnObjectTO afterObj) {
+        this.afterObj = afterObj;
+    }
+
+    /**
+     * Before object getter.
+     *
+     * @return before object.
+     */
+    public ConnObjectTO getBeforeObj() {
+        return beforeObj;
+    }
+
+    /**
+     * Before object setter.
+     *
+     * @param beforeObj object.
+     */
+    public void setBeforeObj(final ConnObjectTO beforeObj) {
+        this.beforeObj = beforeObj;
+    }
+
+    /**
+     * resource name getter.
+     *
+     * @return resource name.
+     */
+    public String getResource() {
+        return resource;
+    }
+
+    /**
+     * Resource name setter.
+     *
+     * @param resource resource name
+     */
+    public void setResource(final String resource) {
+        this.resource = resource;
+    }
+
+    /**
+     * Propagation execution status getter.
+     *
+     * @return status
+     */
+    public PropagationTaskExecStatus getStatus() {
+        return status;
+    }
+
+    /**
+     * Propagation execution status setter.
+     *
+     * @param status propagation execution status
+     */
+    public void setStatus(final PropagationTaskExecStatus status) {
+        this.status = status;
+    }
+
+    /**
+     * Propagation execution message getter.
+     *
+     * @return failureReason.
+     */
+    public String getFailureReason() {
+        return failureReason;
+    }
+
+    /**
+     * Propagation execution failure message setter.
+     *
+     * @param failureReason describes why this propagation failed
+     */
+    public void setFailureReason(final String failureReason) {
+        this.failureReason = failureReason;
+    }
+}


[08/32] syncope git commit: Merge branch '1_2_X'

Posted by il...@apache.org.
Merge branch '1_2_X'


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

Branch: refs/heads/2_0_X
Commit: 08893dc1f4fcdb96742dd3c0892004c829d41843
Parents: 51c543d f3a0871
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Sun Dec 28 14:49:21 2014 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Sun Dec 28 14:49:21 2014 +0100

----------------------------------------------------------------------
 pom.xml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/08893dc1/pom.xml
----------------------------------------------------------------------


[04/32] syncope git commit: Merge branch '1_2_X'

Posted by il...@apache.org.
Merge branch '1_2_X'


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

Branch: refs/heads/2_0_X
Commit: 51c543da581970052942c506021d3329b3853d30
Parents: 86cbfe4 5e013aa
Author: Marco Di Sabatino Di Diodoro <md...@apache.org>
Authored: Mon Dec 22 17:57:14 2014 +0100
Committer: Marco Di Sabatino Di Diodoro <md...@apache.org>
Committed: Mon Dec 22 17:57:14 2014 +0100

----------------------------------------------------------------------
 installer/pom.xml                               |  20 +++
 .../installer/containers/jboss/JBoss.java       |  12 +-
 .../org/apache/syncope/installer/enums/DBs.java |   3 +
 .../installer/files/ConsoleProperties.java      |  31 ++++
 .../syncope/installer/files/CoreWebXml.java     |  76 ++------
 .../installer/files/GlassfishCoreWebXml.java    |  38 +---
 .../files/JBossDeploymentStructureXml.java      |  40 +----
 .../syncope/installer/files/ParentPom.java      | 176 +------------------
 .../files/PersistenceContextEMFactoryXml.java   |  47 +----
 .../installer/files/PersistenceProperties.java  |  27 +--
 .../installer/processes/ArchetypeProcess.java   |  41 +++--
 .../installer/processes/BaseProcess.java        |  54 ++++++
 .../installer/processes/ContainerProcess.java   | 171 ++++++++++++++----
 .../installer/processes/PersistenceProcess.java |  25 ++-
 .../installer/utilities/FileSystemUtils.java    |  45 +++++
 .../syncope/installer/utilities/MavenUtils.java |  31 +---
 .../src/main/resources/configuration.properties |  31 ++++
 .../main/resources/izpack/ProcessPanel.Spec.xml |  40 +++--
 installer/src/main/resources/izpack/install.xml |   6 +-
 .../main/resources/izpack/userInputLang.xml_eng |   4 +
 .../main/resources/izpack/userInputLang.xml_ita |   4 +
 .../src/main/resources/izpack/userInputSpec.xml |  20 ++-
 installer/src/main/resources/modelerPom.xml     | 116 ++++++++++++
 23 files changed, 589 insertions(+), 469 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/51c543da/installer/pom.xml
----------------------------------------------------------------------


[30/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/SubjectDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/SubjectDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/SubjectDAO.java
index 9f8dccc..f542422 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/SubjectDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/SubjectDAO.java
@@ -22,21 +22,23 @@ import java.util.List;
 import org.apache.syncope.persistence.api.entity.AttributableUtil;
 import org.apache.syncope.persistence.api.entity.DerAttr;
 import org.apache.syncope.persistence.api.entity.ExternalResource;
-import org.apache.syncope.persistence.api.entity.NormAttr;
-import org.apache.syncope.persistence.api.entity.NormAttrValue;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
 import org.apache.syncope.persistence.api.entity.Subject;
 import org.apache.syncope.persistence.api.entity.VirAttr;
 
-public interface SubjectDAO<N extends NormAttr, D extends DerAttr<N>, V extends VirAttr> extends DAO<Subject<N, D, V>> {
+public interface SubjectDAO<P extends PlainAttr, D extends DerAttr, V extends VirAttr>
+        extends DAO<Subject<P, D, V>, Long> {
 
-    <T extends Subject<N, D, V>> List<T> findByAttrValue(String schemaName,
-            NormAttrValue attrValue, AttributableUtil attrUtil);
+    List<? extends Subject<P, D, V>> findByAttrValue(
+            String schemaName, PlainAttrValue attrValue, AttributableUtil attrUtil);
 
-    <T extends Subject<N, D, V>> T findByAttrUniqueValue(String schemaName,
-            NormAttrValue attrUniqueValue, AttributableUtil attrUtil);
+    Subject<P, D, V> findByAttrUniqueValue(
+            String schemaName, PlainAttrValue attrUniqueValue, AttributableUtil attrUtil);
 
-    <T extends Subject<N, D, V>> List<T> findByDerAttrValue(
+    List<? extends Subject<P, D, V>> findByDerAttrValue(
             String schemaName, String value, AttributableUtil attrUtil);
 
-    <T extends Subject<N, D, V>> List<T> findByResource(ExternalResource resource, Class<T> reference);
+    List<? extends Subject<P, D, V>> findByResource(
+            ExternalResource resource, AttributableUtil attrUtil);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/SubjectSearchDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/SubjectSearchDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/SubjectSearchDAO.java
index b9cc194..4bb811a 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/SubjectSearchDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/SubjectSearchDAO.java
@@ -23,9 +23,12 @@ import java.util.Set;
 import org.apache.syncope.common.lib.types.SubjectType;
 import org.apache.syncope.persistence.api.dao.search.OrderByClause;
 import org.apache.syncope.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.persistence.api.entity.DerAttr;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
 import org.apache.syncope.persistence.api.entity.Subject;
+import org.apache.syncope.persistence.api.entity.VirAttr;
 
-public interface SubjectSearchDAO extends DAO<Subject<?, ?, ?>> {
+public interface SubjectSearchDAO extends DAO<Subject<?, ?, ?>, Long> {
 
     /**
      * @param adminRoles the set of admin roles owned by the caller
@@ -42,7 +45,8 @@ public interface SubjectSearchDAO extends DAO<Subject<?, ?, ?>> {
      * @param <T> user/role
      * @return the list of users/roles matching the given search condition
      */
-    <T extends Subject<?, ?, ?>> List<T> search(Set<Long> adminRoles, SearchCond searchCondition, SubjectType type);
+    <T extends Subject<?, ?, ?>> List<T> search(
+            Set<Long> adminRoles, SearchCond searchCondition, SubjectType type);
 
     /**
      * @param adminRoles the set of admin roles owned by the caller
@@ -52,8 +56,8 @@ public interface SubjectSearchDAO extends DAO<Subject<?, ?, ?>> {
      * @param <T> user/role
      * @return the list of users/roles matching the given search condition
      */
-    <T extends Subject<?, ?, ?>> List<T> search(Set<Long> adminRoles, SearchCond searchCondition,
-            List<OrderByClause> orderBy, SubjectType type);
+    <T extends Subject<?, ?, ?>> List<T> search(
+            Set<Long> adminRoles, SearchCond searchCondition, List<OrderByClause> orderBy, SubjectType type);
 
     /**
      * @param adminRoles the set of admin roles owned by the caller
@@ -65,8 +69,9 @@ public interface SubjectSearchDAO extends DAO<Subject<?, ?, ?>> {
      * @param <T> user/role
      * @return the list of users/roles matching the given search condition (in the given page)
      */
-    <T extends Subject<?, ?, ?>> List<T> search(Set<Long> adminRoles, SearchCond searchCondition,
-            int page, int itemsPerPage, List<OrderByClause> orderBy, SubjectType type);
+    <T extends Subject<?, ?, ?>> List<T> search(
+            Set<Long> adminRoles, SearchCond searchCondition, int page, int itemsPerPage,
+            List<OrderByClause> orderBy, SubjectType type);
 
     /**
      * Verify if user/role matches the given search condition.

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/TaskDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/TaskDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/TaskDAO.java
index 5ab5b6a..63e4358 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/TaskDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/TaskDAO.java
@@ -19,31 +19,34 @@
 package org.apache.syncope.persistence.api.dao;
 
 import java.util.List;
+import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.persistence.api.dao.search.OrderByClause;
-import org.apache.syncope.persistence.api.dao.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
 import org.apache.syncope.persistence.api.entity.ExternalResource;
 import org.apache.syncope.persistence.api.entity.task.Task;
 
-public interface TaskDAO extends DAO<Task> {
+public interface TaskDAO extends DAO<Task, Long> {
+
+    Class<? extends Task> getEntityReference(TaskType type);
 
     <T extends Task> T find(Long key);
 
-    <T extends Task> List<T> findToExec(Class<T> reference);
+    <T extends Task> List<T> findToExec(TaskType type);
 
-    <T extends Task> List<T> findAll(ExternalResource resource, Class<T> reference);
+    <T extends Task> List<T> findAll(ExternalResource resource, TaskType type);
 
-    <T extends Task> List<T> findAll(Class<T> reference);
+    <T extends Task> List<T> findAll(TaskType type);
 
     <T extends Task> List<T> findAll(
-            int page, int itemsPerPage, List<OrderByClause> orderByClauses, Class<T> reference);
+            int page, int itemsPerPage, List<OrderByClause> orderByClauses, TaskType type);
 
-    <T extends Task> int count(Class<T> reference);
+    int count(TaskType type);
 
     <T extends Task> T save(T task) throws InvalidEntityException;
 
-    <T extends Task> void delete(Long key);
+    void delete(Long key);
 
-    <T extends Task> void delete(T task);
+    void delete(Task task);
 
-    <T extends Task> void deleteAll(ExternalResource resource, Class<T> reference);
+    void deleteAll(ExternalResource resource, TaskType type);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/TaskExecDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/TaskExecDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/TaskExecDAO.java
index 05224b4..7b8d30d 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/TaskExecDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/TaskExecDAO.java
@@ -19,11 +19,12 @@
 package org.apache.syncope.persistence.api.dao;
 
 import java.util.List;
-import org.apache.syncope.persistence.api.dao.validation.InvalidEntityException;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
 import org.apache.syncope.persistence.api.entity.task.Task;
 import org.apache.syncope.persistence.api.entity.task.TaskExec;
 
-public interface TaskExecDAO extends DAO<TaskExec> {
+public interface TaskExecDAO extends DAO<TaskExec, Long> {
 
     TaskExec find(Long key);
 
@@ -31,7 +32,7 @@ public interface TaskExecDAO extends DAO<TaskExec> {
 
     <T extends Task> TaskExec findLatestEnded(T task);
 
-    <T extends Task> List<TaskExec> findAll(Class<T> reference);
+    List<TaskExec> findAll(TaskType type);
 
     TaskExec save(TaskExec execution) throws InvalidEntityException;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/UserDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/UserDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/UserDAO.java
index f70be0a..42ea10a 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/UserDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/UserDAO.java
@@ -21,16 +21,16 @@ package org.apache.syncope.persistence.api.dao;
 import java.util.List;
 import java.util.Set;
 import org.apache.syncope.persistence.api.dao.search.OrderByClause;
-import org.apache.syncope.persistence.api.dao.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
 import org.apache.syncope.persistence.api.entity.ExternalResource;
 import org.apache.syncope.persistence.api.entity.user.SecurityQuestion;
 import org.apache.syncope.persistence.api.entity.user.UDerAttr;
-import org.apache.syncope.persistence.api.entity.user.UNormAttr;
-import org.apache.syncope.persistence.api.entity.user.UNormAttrValue;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttr;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttrValue;
 import org.apache.syncope.persistence.api.entity.user.UVirAttr;
 import org.apache.syncope.persistence.api.entity.user.User;
 
-public interface UserDAO extends SubjectDAO<UNormAttr, UDerAttr, UVirAttr> {
+public interface UserDAO extends SubjectDAO<UPlainAttr, UDerAttr, UVirAttr> {
 
     User find(Long key);
 
@@ -44,9 +44,9 @@ public interface UserDAO extends SubjectDAO<UNormAttr, UDerAttr, UVirAttr> {
 
     List<User> findByDerAttrValue(String schemaName, String value);
 
-    List<User> findByAttrValue(String schemaName, UNormAttrValue attrValue);
+    List<User> findByAttrValue(String schemaName, UPlainAttrValue attrValue);
 
-    User findByAttrUniqueValue(String schemaName, UNormAttrValue attrUniqueValue);
+    User findByAttrUniqueValue(String schemaName, UPlainAttrValue attrUniqueValue);
 
     List<User> findByResource(ExternalResource resource);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/VirAttrDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/VirAttrDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/VirAttrDAO.java
index 7cae917..e8df331 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/VirAttrDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/VirAttrDAO.java
@@ -19,10 +19,10 @@
 package org.apache.syncope.persistence.api.dao;
 
 import java.util.List;
-import org.apache.syncope.persistence.api.dao.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
 import org.apache.syncope.persistence.api.entity.VirAttr;
 
-public interface VirAttrDAO extends DAO<VirAttr> {
+public interface VirAttrDAO extends DAO<VirAttr, Long> {
 
     <T extends VirAttr> T find(Long key, Class<T> reference);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/VirSchemaDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/VirSchemaDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/VirSchemaDAO.java
index a53a9b7..41bdf0f 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/VirSchemaDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/VirSchemaDAO.java
@@ -19,17 +19,18 @@
 package org.apache.syncope.persistence.api.dao;
 
 import java.util.List;
-import org.apache.syncope.persistence.api.dao.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
 import org.apache.syncope.persistence.api.entity.AttributableUtil;
+import org.apache.syncope.persistence.api.entity.VirAttr;
 import org.apache.syncope.persistence.api.entity.VirSchema;
 
-public interface VirSchemaDAO extends DAO<VirSchema> {
+public interface VirSchemaDAO extends DAO<VirSchema, String> {
 
     <T extends VirSchema> T find(String key, Class<T> reference);
 
     <T extends VirSchema> List<T> findAll(Class<T> reference);
 
-    <T extends VirSchema> List<T> findAttrs(VirSchema virSchema, Class<T> reference);
+    <T extends VirAttr> List<T> findAttrs(VirSchema virSchema, Class<T> reference);
 
     <T extends VirSchema> T save(T virSchema) throws InvalidEntityException;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/validation/InvalidEntityException.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/validation/InvalidEntityException.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/validation/InvalidEntityException.java
deleted file mode 100644
index 1961173..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/validation/InvalidEntityException.java
+++ /dev/null
@@ -1,129 +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.persistence.api.dao.validation;
-
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import javax.validation.ConstraintViolation;
-import javax.validation.ValidationException;
-import org.apache.syncope.common.lib.types.EntityViolationType;
-
-/**
- * Exception thrown when any JPA entity fails bean validation.
- */
-public class InvalidEntityException extends ValidationException {
-
-    private static final long serialVersionUID = 3249297275444409691L;
-
-    private final String entityClassSimpleName;
-
-    private final Map<Class<?>, Set<EntityViolationType>> violations = new HashMap<>();
-
-    /**
-     * Constructs a singleton map of violations from given parameters.
-     *
-     * @param entityClass class of invalid entity
-     * @param entityViolationType type of violation found
-     * @param message message to be associated to the violation
-     */
-    public InvalidEntityException(final Class<?> entityClass,
-            final EntityViolationType entityViolationType, final String message) {
-
-        super();
-
-        this.entityClassSimpleName = entityClass.getSimpleName();
-
-        entityViolationType.setMessage(message.trim());
-
-        this.violations.put(entityClass, EnumSet.noneOf(EntityViolationType.class));
-        this.violations.get(entityClass).add(entityViolationType);
-    }
-
-    /**
-     * Constructs a map of violations out of given <tt>ConstraintViolation</tt> set.
-     *
-     * @param entityClassSimpleName simple class name of invalid entity
-     * @param violations as returned by bean validation
-     */
-    public InvalidEntityException(final String entityClassSimpleName,
-            final Set<ConstraintViolation<Object>> violations) {
-
-        super();
-
-        this.entityClassSimpleName = entityClassSimpleName;
-
-        for (ConstraintViolation<Object> violation : violations) {
-            int firstComma = violation.getMessageTemplate().indexOf(';');
-
-            final String key = violation.getMessageTemplate().substring(
-                    0, firstComma > 0 ? firstComma : violation.getMessageTemplate().length());
-
-            final String message = violation.getMessageTemplate().substring(firstComma > 0 ? firstComma + 1 : 0);
-
-            EntityViolationType entityViolationType;
-
-            try {
-                entityViolationType = EntityViolationType.valueOf(key.trim());
-            } catch (IllegalArgumentException e) {
-                entityViolationType = EntityViolationType.Standard;
-            }
-
-            entityViolationType.setMessage(message.trim());
-
-            if (!this.violations.containsKey(violation.getLeafBean().getClass())) {
-                this.violations.put(violation.getLeafBean().getClass(), EnumSet.noneOf(EntityViolationType.class));
-            }
-
-            this.violations.get(violation.getLeafBean().getClass()).add(entityViolationType);
-        }
-    }
-
-    public final boolean hasViolation(final EntityViolationType type) {
-        boolean found = false;
-        for (Class<?> entity : violations.keySet()) {
-            if (violations.get(entity).contains(type)) {
-                found = true;
-            }
-        }
-
-        return found;
-    }
-
-    public String getEntityClassSimpleName() {
-        return entityClassSimpleName;
-    }
-
-    public final Map<Class<?>, Set<EntityViolationType>> getViolations() {
-        return violations;
-    }
-
-    @Override
-    public String getMessage() {
-        StringBuilder sb = new StringBuilder();
-
-        for (Class<?> entity : violations.keySet()) {
-            sb.append(entity.getSimpleName()).append(" ").append(violations.get(entity).toString()).append(", ");
-        }
-        sb.delete(sb.lastIndexOf(", "), sb.length());
-
-        return sb.toString();
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/validation/InvalidNormAttrValueException.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/validation/InvalidNormAttrValueException.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/validation/InvalidNormAttrValueException.java
deleted file mode 100644
index 6afcd13..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/validation/InvalidNormAttrValueException.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.persistence.api.dao.validation;
-
-import javax.validation.ValidationException;
-import org.apache.syncope.persistence.api.entity.NormAttrValue;
-
-public class InvalidNormAttrValueException extends ValidationException {
-
-    private static final long serialVersionUID = -5023202610580202148L;
-
-    public InvalidNormAttrValueException(final String errorMessage) {
-        super(errorMessage);
-    }
-
-    public InvalidNormAttrValueException(final String errorMessage, final Throwable cause) {
-        super(errorMessage, cause);
-    }
-
-    public InvalidNormAttrValueException(final NormAttrValue value) {
-        this("Could not validate " + value.getValue());
-    }
-
-    public InvalidNormAttrValueException(final NormAttrValue value, Throwable cause) {
-        this("Could not validate " + value.getValue(), cause);
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/validation/ParsingValidationException.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/validation/ParsingValidationException.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/validation/ParsingValidationException.java
deleted file mode 100644
index 056bfb9..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/validation/ParsingValidationException.java
+++ /dev/null
@@ -1,30 +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.persistence.api.dao.validation;
-
-import javax.validation.ValidationException;
-
-public class ParsingValidationException extends ValidationException {
-
-    private static final long serialVersionUID = 5669262895008285522L;
-
-    public ParsingValidationException(final String message, final Throwable cause) {
-        super(message, cause);
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/validation/Validator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/validation/Validator.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/validation/Validator.java
deleted file mode 100644
index 3d439a7..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/validation/Validator.java
+++ /dev/null
@@ -1,26 +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.persistence.api.dao.validation;
-
-import org.apache.syncope.persistence.api.entity.NormAttrValue;
-
-public interface Validator {
-
-    void validate(String value, NormAttrValue attrValue) throws ParsingValidationException, InvalidNormAttrValueException;
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AccountPolicy.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AccountPolicy.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AccountPolicy.java
index 2570f20..912c622 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AccountPolicy.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AccountPolicy.java
@@ -18,18 +18,15 @@
  */
 package org.apache.syncope.persistence.api.entity;
 
-import java.util.Collection;
 import java.util.Set;
 
 public interface AccountPolicy extends Policy {
 
-    Set<String> getResourceNames();
-
-    Set<ExternalResource> getResources();
-
     boolean addResource(ExternalResource resource);
 
     boolean removeResource(ExternalResource resource);
 
-    void setResources(Collection<ExternalResource> resources);
+    Set<String> getResourceNames();
+
+    Set<? extends ExternalResource> getResources();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Attr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Attr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Attr.java
index 7a54213..bb81373 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Attr.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Attr.java
@@ -25,6 +25,6 @@ public interface Attr<S extends Schema> extends Entity<Long> {
     void setOwner(Attributable<?, ?, ?> owner);
 
     S getSchema();
-    
+
     void setSchema(S schema);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttrTemplate.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttrTemplate.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttrTemplate.java
index 0055b69..c016223 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttrTemplate.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttrTemplate.java
@@ -20,13 +20,13 @@ package org.apache.syncope.persistence.api.entity;
 
 import org.apache.syncope.persistence.api.entity.role.Role;
 
-public interface AttrTemplate<T extends Schema> extends Entity<Long> {
+public interface AttrTemplate<S extends Schema> extends Entity<Long> {
 
     Role getOwner();
 
     void setOwner(Role role);
 
-    T getSchema();
+    S getSchema();
 
-    void setSchema(T schema);
+    void setSchema(S schema);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Attributable.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Attributable.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Attributable.java
index 31eb9a4..350a524 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Attributable.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Attributable.java
@@ -20,29 +20,29 @@ package org.apache.syncope.persistence.api.entity;
 
 import java.util.List;
 
-public interface Attributable<N extends NormAttr, D extends DerAttr, V extends VirAttr> extends AnnotatedEntity<Long> {
+public interface Attributable<P extends PlainAttr, D extends DerAttr, V extends VirAttr> extends AnnotatedEntity<Long> {
 
-    boolean addNormAttr(N attr);
+    boolean addPlainAttr(P attr);
 
-    boolean addDerAttr(D attr);
+    boolean addDerAttr(D derAttr);
 
-    boolean addVirAttr(V attr);
+    boolean addVirAttr(V virAttr);
 
-    N getNormAttr(String normSchemaName);
+    boolean removePlainAttr(P attr);
 
-    List<N> getNormAttrs();
+    boolean removeDerAttr(D derAttr);
 
-    D getDerAttr(String derSchemaName);
+    boolean removeVirAttr(V virAttr);
 
-    List<D> getDerAttrs();
+    P getPlainAttr(String plainSchemaName);
 
-    V getVirAttr(String virSchemaName);
+    List<? extends P> getPlainAttrs();
 
-    List<V> getVirAttrs();
+    D getDerAttr(String derSchemaName);
 
-    boolean removeNormAttr(N attr);
+    List<? extends D> getDerAttrs();
 
-    boolean removeDerAttr(D derAttr);
+    V getVirAttr(String virSchemaName);
 
-    boolean removeVirAttr(V virAttr);
+    List<? extends V> getVirAttrs();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttributableUtil.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttributableUtil.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttributableUtil.java
index 58205fd..ff1679c 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttributableUtil.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttributableUtil.java
@@ -27,23 +27,25 @@ public interface AttributableUtil {
 
     AttributableType getType();
 
-    <T extends Attributable> Class<T> attributableClass();
+    <T extends Attributable<?, ?, ?>> Class<T> attributableClass();
 
-    <T extends NormSchema> Class<T> normSchemaClass();
+    <T extends PlainSchema> Class<T> plainSchemaClass();
 
-    <T extends NormAttr> Class<T> normAttrClass();
+    <T extends PlainSchema> T newPlainSchema();
 
-    <T extends NormAttr> T newNormAttr();
+    <T extends PlainAttr> Class<T> plainAttrClass();
 
-    <T extends NormAttrValue> Class<T> attrUniqueValueClass();
+    <T extends PlainAttr> T newPlainAttr();
 
-    <T extends NormAttrValue> T newNormAttrUniqueValue();
+    <T extends PlainAttrValue> Class<T> plainAttrValueClass();
 
-    <T extends NormAttrValue> Class<T> attrValueClass();
+    <T extends PlainAttrValue> T newPlainAttrValue();
 
-    <T extends NormAttrValue> T newNormAttrValue();
+    <T extends AttrTemplate<PlainSchema>> Class<T> plainAttrTemplateClass();
 
-    <T extends AttrTemplate<NormSchema>> Class<T> normAttrTemplateClass();
+    <T extends PlainAttrValue> Class<T> plainAttrUniqueValueClass();
+
+    <T extends PlainAttrValue> T newPlainAttrUniqueValue();
 
     <T extends DerSchema> Class<T> derSchemaClass();
 
@@ -71,8 +73,7 @@ public interface AttributableUtil {
 
     <T extends MappingItem> List<T> getMappingItems(ExternalResource resource, MappingPurpose purpose);
 
-    <T extends MappingItem> List<T> getUidToMappingItems(
-            ExternalResource resource, MappingPurpose purpose, AttributableType type);
+    <T extends MappingItem> List<T> getUidToMappingItems(ExternalResource resource, MappingPurpose purpose);
 
     IntMappingType intMappingType();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ConnInstance.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ConnInstance.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ConnInstance.java
index e582779..21d8286 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ConnInstance.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ConnInstance.java
@@ -45,7 +45,7 @@ public interface ConnInstance extends Entity<Long> {
 
     ConnPoolConf getPoolConf();
 
-    List<ExternalResource> getResources();
+    List<? extends ExternalResource> getResources();
 
     String getVersion();
 
@@ -55,11 +55,9 @@ public interface ConnInstance extends Entity<Long> {
 
     void setBundleName(String bundleName);
 
-    void setCapabilities(Set<ConnectorCapability> capabilities);
-
     void setConfiguration(Set<ConnConfProperty> configuration);
 
-    void setConnRequestTimeout(Integer connRequestTimeout);
+    void setConnRequestTimeout(Integer timeout);
 
     void setConnectorName(String connectorName);
 
@@ -69,7 +67,5 @@ public interface ConnInstance extends Entity<Long> {
 
     void setPoolConf(ConnPoolConf poolConf);
 
-    void setResources(List<ExternalResource> resources);
-
     void setVersion(String version);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/DerAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/DerAttr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/DerAttr.java
index 7a6812e..0494d01 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/DerAttr.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/DerAttr.java
@@ -20,7 +20,7 @@ package org.apache.syncope.persistence.api.entity;
 
 import java.util.Collection;
 
-public interface DerAttr<N extends NormAttr> extends Attr<DerSchema> {
+public interface DerAttr extends Attr<DerSchema> {
 
-    String getValue(Collection<N> attrs);
+    String getValue(Collection<? extends PlainAttr> attrs);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ExternalResource.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ExternalResource.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ExternalResource.java
index 3e96e13..965c1a5 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ExternalResource.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ExternalResource.java
@@ -99,10 +99,6 @@ public interface ExternalResource extends Entity<String> {
 
     void setRmapping(RMapping rmapping);
 
-    void setSerializedUSyncToken(String token);
-
-    void setSerializedRSyncToken(String token);
-
     void setEnforceMandatoryCondition(boolean enforce);
 
     void setPropagationPrimary(boolean condition);

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Logger.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Logger.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Logger.java
index ca6e17b..1284833 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Logger.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Logger.java
@@ -23,7 +23,7 @@ import org.apache.syncope.common.lib.types.LoggerType;
 
 public interface Logger extends Entity<String> {
 
-    void setName(String name);
+    void setKey(String name);
 
     LoggerLevel getLevel();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Mapping.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Mapping.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Mapping.java
index 9e538a6..3639e8e 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Mapping.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Mapping.java
@@ -26,7 +26,7 @@ public interface Mapping<T extends MappingItem> extends Entity<Long> {
 
     String getAccountLink();
 
-    List<T> getItems();
+    List<? extends T> getItems();
 
     ExternalResource getResource();
 
@@ -38,7 +38,5 @@ public interface Mapping<T extends MappingItem> extends Entity<Long> {
 
     void setAccountLink(String accountLink);
 
-    void setItems(List<T> items);
-
     void setResource(ExternalResource resource);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/MappingItem.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/MappingItem.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/MappingItem.java
index 33d3127..07a12b8 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/MappingItem.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/MappingItem.java
@@ -31,7 +31,7 @@ public interface MappingItem extends Entity<Long> {
 
     String getMandatoryCondition();
 
-    <T extends MappingItem> Mapping<T> getMapping();
+    Mapping<?> getMapping();
 
     MappingPurpose getPurpose();
 
@@ -49,7 +49,7 @@ public interface MappingItem extends Entity<Long> {
 
     void setMandatoryCondition(String condition);
 
-    void setMapping(Mapping mapping);
+    void setMapping(Mapping<?> mapping);
 
     void setPassword(boolean password);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/NormAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/NormAttr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/NormAttr.java
deleted file mode 100644
index c5bbccb..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/NormAttr.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.persistence.api.entity;
-
-import java.util.List;
-import org.apache.syncope.persistence.api.dao.validation.InvalidNormAttrValueException;
-
-public interface NormAttr extends Attr<NormSchema> {
-
-    void addValue(String value, AttributableUtil attributableUtil) throws InvalidNormAttrValueException;
-
-    NormAttrValue getUniqueValue();
-
-    List<? extends NormAttrValue> getValues();
-
-    List<String> getValuesAsStrings();
-
-    boolean removeValue(NormAttrValue attrValue);
-
-    void setUniqueValue(NormAttrValue uniqueValue);
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/NormAttrValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/NormAttrValue.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/NormAttrValue.java
deleted file mode 100644
index 3873c70..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/NormAttrValue.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.persistence.api.entity;
-
-import java.util.Date;
-import org.apache.syncope.common.lib.types.AttrSchemaType;
-import org.apache.syncope.persistence.api.dao.validation.ParsingValidationException;
-
-public interface NormAttrValue extends Entity<Long> {
-
-    NormAttr getNormAttr();
-
-    byte[] getBinaryValue();
-
-    Boolean getBooleanValue();
-
-    Date getDateValue();
-
-    Double getDoubleValue();
-
-    Long getLongValue();
-
-    String getStringValue();
-
-    <V> V getValue();
-
-    String getValueAsString();
-
-    String getValueAsString(AttrSchemaType type);
-
-    void parseValue(NormSchema schema, String value) throws ParsingValidationException;
-
-    void setNormAttr(NormAttr attr);
-
-    void setBinaryValue(byte[] binaryValue);
-
-    void setBooleanValue(Boolean booleanValue);
-
-    void setDateValue(Date dateValue);
-
-    void setDoubleValue(Double doubleValue);
-
-    void setLongValue(Long longValue);
-
-    void setStringValue(String stringValue);
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/NormSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/NormSchema.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/NormSchema.java
deleted file mode 100644
index 53072ad..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/NormSchema.java
+++ /dev/null
@@ -1,56 +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.persistence.api.entity;
-
-import org.apache.syncope.common.lib.types.CipherAlgorithm;
-import org.apache.syncope.persistence.api.dao.validation.Validator;
-
-public interface NormSchema extends Schema {
-
-    CipherAlgorithm getCipherAlgorithm();
-
-    String getConversionPattern();
-
-    String getEnumerationKeys();
-
-    String getEnumerationValues();
-
-    String getMimeType();
-
-    String getSecretKey();
-
-    Validator getValidator();
-
-    String getValidatorClass();
-
-    void setCipherAlgorithm(CipherAlgorithm cipherAlgorithm);
-
-    void setConversionPattern(String conversionPattern);
-
-    void setEnumerationKeys(String enumerationKeys);
-
-    void setEnumerationValues(String enumerationValues);
-
-    void setMimeType(String mimeType);
-
-    void setSecretKey(String secretKey);
-
-    void setValidatorClass(String validatorClass);
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Notification.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Notification.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Notification.java
index d4aaaa9..d7f7dc0 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Notification.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Notification.java
@@ -30,8 +30,6 @@ public interface Notification extends Entity<Long> {
 
     List<String> getEvents();
 
-    Long getId();
-
     String getRecipientAttrName();
 
     IntMappingType getRecipientAttrType();
@@ -62,8 +60,6 @@ public interface Notification extends Entity<Long> {
 
     void setActive(boolean active);
 
-    void setEvents(List<String> events);
-
     void setRecipientAttrName(String recipientAttrName);
 
     void setRecipientAttrType(IntMappingType recipientAttrType);
@@ -76,8 +72,6 @@ public interface Notification extends Entity<Long> {
 
     void setSender(String sender);
 
-    void setStaticRecipients(List<String> staticRecipients);
-
     void setSubject(String subject);
 
     void setTemplate(String template);

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PlainAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PlainAttr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PlainAttr.java
new file mode 100644
index 0000000..d5b2d6e
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PlainAttr.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.persistence.api.entity;
+
+import java.util.List;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidPlainAttrValueException;
+
+public interface PlainAttr extends Attr<PlainSchema> {
+
+    void addValue(String value, AttributableUtil attributableUtil) throws InvalidPlainAttrValueException;
+
+    boolean removeValue(PlainAttrValue attrValue);
+
+    PlainAttrUniqueValue getUniqueValue();
+
+    List<? extends PlainAttrValue> getValues();
+
+    List<String> getValuesAsStrings();
+
+    void setUniqueValue(PlainAttrUniqueValue uniqueValue);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PlainAttrUniqueValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PlainAttrUniqueValue.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PlainAttrUniqueValue.java
new file mode 100644
index 0000000..6f7113a
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PlainAttrUniqueValue.java
@@ -0,0 +1,26 @@
+/*
+ * 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.persistence.api.entity;
+
+public interface PlainAttrUniqueValue extends PlainAttrValue {
+
+    PlainSchema getSchema();
+
+    void setSchema(PlainSchema schema);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PlainAttrValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PlainAttrValue.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PlainAttrValue.java
new file mode 100644
index 0000000..da7f1c3
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PlainAttrValue.java
@@ -0,0 +1,62 @@
+/*
+ * 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.persistence.api.entity;
+
+import java.util.Date;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.persistence.api.attrvalue.validation.ParsingValidationException;
+
+public interface PlainAttrValue extends Entity<Long> {
+
+    PlainAttr getAttr();
+
+    byte[] getBinaryValue();
+
+    Boolean getBooleanValue();
+
+    Date getDateValue();
+
+    Double getDoubleValue();
+
+    Long getLongValue();
+
+    String getStringValue();
+
+    <V> V getValue();
+
+    String getValueAsString();
+
+    String getValueAsString(AttrSchemaType type);
+
+    void parseValue(PlainSchema schema, String value) throws ParsingValidationException;
+
+    void setAttr(PlainAttr attr);
+
+    void setBinaryValue(byte[] binaryValue);
+
+    void setBooleanValue(Boolean booleanValue);
+
+    void setDateValue(Date dateValue);
+
+    void setDoubleValue(Double doubleValue);
+
+    void setLongValue(Long longValue);
+
+    void setStringValue(String stringValue);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PlainSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PlainSchema.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PlainSchema.java
new file mode 100644
index 0000000..2ba286c
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PlainSchema.java
@@ -0,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.persistence.api.entity;
+
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.CipherAlgorithm;
+import org.apache.syncope.persistence.api.attrvalue.validation.Validator;
+
+public interface PlainSchema extends Schema {
+
+    CipherAlgorithm getCipherAlgorithm();
+
+    String getConversionPattern();
+
+    String getEnumerationKeys();
+
+    String getEnumerationValues();
+
+    String getMimeType();
+
+    String getSecretKey();
+
+    Validator getValidator();
+
+    String getValidatorClass();
+
+    void setCipherAlgorithm(CipherAlgorithm cipherAlgorithm);
+
+    void setConversionPattern(String conversionPattern);
+
+    void setEnumerationKeys(String enumerationKeys);
+
+    void setEnumerationValues(String enumerationValues);
+
+    void setMimeType(String mimeType);
+
+    void setSecretKey(String secretKey);
+
+    void setValidatorClass(String validatorClass);
+
+    void setType(AttrSchemaType type);
+
+    void setMandatoryCondition(String condition);
+
+    void setMultivalue(boolean multivalue);
+
+    void setReadonly(boolean readonly);
+
+    void setUniqueConstraint(boolean uniquevalue);
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PushPolicy.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PushPolicy.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PushPolicy.java
new file mode 100644
index 0000000..d97ad64
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/PushPolicy.java
@@ -0,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.persistence.api.entity;
+
+public interface PushPolicy extends Policy {
+    
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Report.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Report.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Report.java
index f158743..09fe063 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Report.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Report.java
@@ -31,9 +31,9 @@ public interface Report extends Entity<Long> {
 
     String getCronExpression();
 
-    List<ReportExec> getExecs();
+    List<? extends ReportExec> getExecs();
 
-    List<ReportletConf> getReportletConfs();
+    List<? extends ReportletConf> getReportletConfs();
 
     boolean removeExec(ReportExec exec);
 
@@ -41,9 +41,5 @@ public interface Report extends Entity<Long> {
 
     void setCronExpression(String cronExpression);
 
-    void setExecs(List<ReportExec> executions);
-
     void setName(String name);
-
-    void setReportletConfs(List<ReportletConf> reportletConfs);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ReportletConfInstance.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ReportletConfInstance.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ReportletConfInstance.java
new file mode 100644
index 0000000..dcf56ed
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ReportletConfInstance.java
@@ -0,0 +1,33 @@
+/*
+ * 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.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);
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Schema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Schema.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Schema.java
index d05f8ec..2e4a5eb 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Schema.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Schema.java
@@ -32,16 +32,6 @@ public interface Schema extends Entity<String> {
 
     boolean isUniqueConstraint();
 
-    void setName(String name);
-
-    void setType(AttrSchemaType type);
-
-    void setMandatoryCondition(String condition);
-
-    void setMultivalue(boolean multivalue);
-
-    void setReadonly(boolean readonly);
-
-    void setUniqueConstraint(boolean uniquevalue);
+    void setKey(String name);
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Subject.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Subject.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Subject.java
index d75bcfa..7f13b03 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Subject.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Subject.java
@@ -20,7 +20,7 @@ package org.apache.syncope.persistence.api.entity;
 
 import java.util.Set;
 
-public interface Subject<N extends NormAttr, D extends DerAttr<N>, V extends VirAttr> extends Attributable<N, D, V> {
+public interface Subject<N extends PlainAttr, D extends DerAttr, V extends VirAttr> extends Attributable<N, D, V> {
 
     boolean addResource(ExternalResource resource);
 
@@ -28,7 +28,5 @@ public interface Subject<N extends NormAttr, D extends DerAttr<N>, V extends Vir
 
     Set<String> getResourceNames();
 
-    Set<ExternalResource> getResources();
-
-    void setResources(Set<ExternalResource> resources);
+    Set<? extends ExternalResource> getResources();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/VirAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/VirAttr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/VirAttr.java
index ce39d36..a7287c7 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/VirAttr.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/VirAttr.java
@@ -27,6 +27,4 @@ public interface VirAttr extends Attr<VirSchema> {
     boolean addValue(String value);
 
     boolean removeValue(String value);
-
-    void setValues(List<String> values);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/VirSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/VirSchema.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/VirSchema.java
index d222ac5..274aa8c 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/VirSchema.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/VirSchema.java
@@ -20,4 +20,5 @@ package org.apache.syncope.persistence.api.entity;
 
 public interface VirSchema extends Schema {
 
+    void setReadonly(boolean readonly);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CNormAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CNormAttr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CNormAttr.java
deleted file mode 100644
index a294321..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CNormAttr.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.persistence.api.entity.conf;
-
-import org.apache.syncope.persistence.api.entity.NormAttr;
-
-public interface CNormAttr extends NormAttr {
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CPlainAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CPlainAttr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CPlainAttr.java
new file mode 100644
index 0000000..3636d52
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CPlainAttr.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.persistence.api.entity.conf;
+
+import java.util.List;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+
+public interface CPlainAttr extends PlainAttr {
+
+    @SuppressWarnings("unchecked")
+    @Override
+    Conf getOwner();
+
+    @Override
+    CPlainSchema getSchema();
+
+    @Override
+    List<? extends CPlainAttrValue> getValues();
+
+    @Override
+    CPlainAttrUniqueValue getUniqueValue();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CPlainAttrUniqueValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CPlainAttrUniqueValue.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CPlainAttrUniqueValue.java
new file mode 100644
index 0000000..3c27fbb
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CPlainAttrUniqueValue.java
@@ -0,0 +1,31 @@
+/*
+ * 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.persistence.api.entity.conf;
+
+import org.apache.syncope.persistence.api.entity.PlainAttrUniqueValue;
+
+public interface CPlainAttrUniqueValue extends PlainAttrUniqueValue {
+
+    @Override
+    CPlainAttr getAttr();
+
+    @Override
+    CPlainSchema getSchema();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CPlainAttrValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CPlainAttrValue.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CPlainAttrValue.java
new file mode 100644
index 0000000..dbf8ba5
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CPlainAttrValue.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.persistence.api.entity.conf;
+
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+
+public interface CPlainAttrValue extends PlainAttrValue {
+
+    @Override
+    CPlainAttr getAttr();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CPlainSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CPlainSchema.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CPlainSchema.java
new file mode 100644
index 0000000..aa2fbfc
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/CPlainSchema.java
@@ -0,0 +1,25 @@
+/*
+ * 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.persistence.api.entity.conf;
+
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+
+public interface CPlainSchema extends PlainSchema {
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/Conf.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/Conf.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/Conf.java
index 4c559c6..5a3b28d 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/Conf.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/conf/Conf.java
@@ -23,17 +23,17 @@ import org.apache.syncope.persistence.api.entity.Attributable;
 import org.apache.syncope.persistence.api.entity.DerAttr;
 import org.apache.syncope.persistence.api.entity.VirAttr;
 
-public interface Conf extends Attributable<CNormAttr, DerAttr<CNormAttr>, VirAttr> {
+public interface Conf extends Attributable<CPlainAttr, DerAttr, VirAttr> {
 
-    @Override
-    boolean addNormAttr(CNormAttr attr);
+    void setKey(Long key);
 
     @Override
-    CNormAttr getNormAttr(String normSchemaName);
+    boolean addPlainAttr(CPlainAttr attr);
 
     @Override
-    List<CNormAttr> getNormAttrs();
+    boolean removePlainAttr(CPlainAttr attr);
 
     @Override
-    boolean removeNormAttr(CNormAttr attr);
+    List<? extends CPlainAttr> getPlainAttrs();
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MDerAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MDerAttr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MDerAttr.java
index 8cb04f8..26dcd91 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MDerAttr.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MDerAttr.java
@@ -20,7 +20,13 @@ package org.apache.syncope.persistence.api.entity.membership;
 
 import org.apache.syncope.persistence.api.entity.DerAttr;
 
-public interface MDerAttr extends DerAttr<MNormAttr> {
+public interface MDerAttr extends DerAttr {
+
+    @Override
+    Membership getOwner();
+
+    @Override
+    MDerSchema getSchema();
 
     MDerAttrTemplate getTemplate();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MDerAttrTemplate.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MDerAttrTemplate.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MDerAttrTemplate.java
index 55c1c9f..2413e9a 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MDerAttrTemplate.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MDerAttrTemplate.java
@@ -19,8 +19,7 @@
 package org.apache.syncope.persistence.api.entity.membership;
 
 import org.apache.syncope.persistence.api.entity.AttrTemplate;
-import org.apache.syncope.persistence.api.entity.DerSchema;
 
-public interface MDerAttrTemplate extends AttrTemplate<DerSchema> {
+public interface MDerAttrTemplate extends AttrTemplate<MDerSchema> {
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MDerSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MDerSchema.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MDerSchema.java
new file mode 100644
index 0000000..554b064
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MDerSchema.java
@@ -0,0 +1,25 @@
+/*
+ * 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.persistence.api.entity.membership;
+
+import org.apache.syncope.persistence.api.entity.DerSchema;
+
+public interface MDerSchema extends DerSchema {
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MNormAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MNormAttr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MNormAttr.java
deleted file mode 100644
index 9804358..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MNormAttr.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.persistence.api.entity.membership;
-
-import org.apache.syncope.persistence.api.entity.NormAttr;
-
-public interface MNormAttr extends NormAttr {
-
-    MNormAttrTemplate getTemplate();
-
-    void setTemplate(MNormAttrTemplate template);
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MNormAttrTemplate.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MNormAttrTemplate.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MNormAttrTemplate.java
deleted file mode 100644
index 7c21c40..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MNormAttrTemplate.java
+++ /dev/null
@@ -1,26 +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.persistence.api.entity.membership;
-
-import org.apache.syncope.persistence.api.entity.AttrTemplate;
-import org.apache.syncope.persistence.api.entity.NormSchema;
-
-public interface MNormAttrTemplate extends AttrTemplate<NormSchema> {
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MNormAttrValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MNormAttrValue.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MNormAttrValue.java
deleted file mode 100644
index 5031c7d..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MNormAttrValue.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.persistence.api.entity.membership;
-
-import org.apache.syncope.persistence.api.entity.NormAttrValue;
-
-public interface MNormAttrValue extends NormAttrValue {
-
-}


[29/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainAttr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainAttr.java
new file mode 100644
index 0000000..b134b01
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainAttr.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.persistence.api.entity.membership;
+
+import java.util.List;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+
+public interface MPlainAttr extends PlainAttr {
+
+    @Override
+    Membership getOwner();
+
+    @Override
+    MPlainSchema getSchema();
+
+    MPlainAttrTemplate getTemplate();
+
+    void setTemplate(MPlainAttrTemplate template);
+
+    @Override
+    List<? extends MPlainAttrValue> getValues();
+
+    @Override
+    MPlainAttrUniqueValue getUniqueValue();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainAttrTemplate.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainAttrTemplate.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainAttrTemplate.java
new file mode 100644
index 0000000..ac6ab91
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainAttrTemplate.java
@@ -0,0 +1,25 @@
+/*
+ * 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.persistence.api.entity.membership;
+
+import org.apache.syncope.persistence.api.entity.AttrTemplate;
+
+public interface MPlainAttrTemplate extends AttrTemplate<MPlainSchema> {
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainAttrUniqueValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainAttrUniqueValue.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainAttrUniqueValue.java
new file mode 100644
index 0000000..a611d8a
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainAttrUniqueValue.java
@@ -0,0 +1,31 @@
+/*
+ * 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.persistence.api.entity.membership;
+
+import org.apache.syncope.persistence.api.entity.PlainAttrUniqueValue;
+
+public interface MPlainAttrUniqueValue extends PlainAttrUniqueValue {
+
+    @Override
+    MPlainAttr getAttr();
+
+    @Override
+    MPlainSchema getSchema();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainAttrValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainAttrValue.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainAttrValue.java
new file mode 100644
index 0000000..6518ae3
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainAttrValue.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.persistence.api.entity.membership;
+
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+
+public interface MPlainAttrValue extends PlainAttrValue {
+
+    @Override
+    MPlainAttr getAttr();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainSchema.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainSchema.java
new file mode 100644
index 0000000..3af8f97
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MPlainSchema.java
@@ -0,0 +1,25 @@
+/*
+ * 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.persistence.api.entity.membership;
+
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+
+public interface MPlainSchema extends PlainSchema {
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MVirAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MVirAttr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MVirAttr.java
index 43e42fe..17a74ca 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MVirAttr.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MVirAttr.java
@@ -22,6 +22,12 @@ import org.apache.syncope.persistence.api.entity.VirAttr;
 
 public interface MVirAttr extends VirAttr {
 
+    @Override
+    Membership getOwner();
+
+    @Override
+    MVirSchema getSchema();
+
     MVirAttrTemplate getTemplate();
 
     void setTemplate(MVirAttrTemplate template);

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MVirAttrTemplate.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MVirAttrTemplate.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MVirAttrTemplate.java
index 6a47df0..1f3a688 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MVirAttrTemplate.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MVirAttrTemplate.java
@@ -19,8 +19,7 @@
 package org.apache.syncope.persistence.api.entity.membership;
 
 import org.apache.syncope.persistence.api.entity.AttrTemplate;
-import org.apache.syncope.persistence.api.entity.VirSchema;
 
-public interface MVirAttrTemplate extends AttrTemplate<VirSchema> {
+public interface MVirAttrTemplate extends AttrTemplate<MVirSchema> {
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MVirSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MVirSchema.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MVirSchema.java
new file mode 100644
index 0000000..8d5fa7b
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/MVirSchema.java
@@ -0,0 +1,25 @@
+/*
+ * 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.persistence.api.entity.membership;
+
+import org.apache.syncope.persistence.api.entity.VirSchema;
+
+public interface MVirSchema extends VirSchema {
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/Membership.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/Membership.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/Membership.java
index 15c2ad0..d07dbd6 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/Membership.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/membership/Membership.java
@@ -23,7 +23,7 @@ import org.apache.syncope.persistence.api.entity.Attributable;
 import org.apache.syncope.persistence.api.entity.role.Role;
 import org.apache.syncope.persistence.api.entity.user.User;
 
-public interface Membership extends Attributable<MNormAttr, MDerAttr, MVirAttr> {
+public interface Membership extends Attributable<MPlainAttr, MDerAttr, MVirAttr> {
 
     Role getRole();
 
@@ -34,38 +34,20 @@ public interface Membership extends Attributable<MNormAttr, MDerAttr, MVirAttr>
     void setUser(User user);
 
     @Override
-    boolean addNormAttr(MNormAttr attr);
+    MPlainAttr getPlainAttr(String plainSchemaName);
 
     @Override
-    boolean addDerAttr(MDerAttr attr);
-
-    @Override
-    boolean addVirAttr(MVirAttr attr);
-
-    @Override
-    MNormAttr getNormAttr(String normSchemaName);
-
-    @Override
-    List<MNormAttr> getNormAttrs();
+    List<? extends MPlainAttr> getPlainAttrs();
 
     @Override
     MDerAttr getDerAttr(String derSchemaName);
 
     @Override
-    List<MDerAttr> getDerAttrs();
+    List<? extends MDerAttr> getDerAttrs();
 
     @Override
     MVirAttr getVirAttr(String virSchemaName);
 
     @Override
-    List<MVirAttr> getVirAttrs();
-
-    @Override
-    boolean removeNormAttr(MNormAttr attr);
-
-    @Override
-    boolean removeDerAttr(MDerAttr derAttr);
-
-    @Override
-    boolean removeVirAttr(MVirAttr virAttr);
+    List<? extends MVirAttr> getVirAttrs();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RDerAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RDerAttr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RDerAttr.java
index b08c0a6..16a0c4e 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RDerAttr.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RDerAttr.java
@@ -20,7 +20,13 @@ package org.apache.syncope.persistence.api.entity.role;
 
 import org.apache.syncope.persistence.api.entity.DerAttr;
 
-public interface RDerAttr extends DerAttr<RNormAttr> {
+public interface RDerAttr extends DerAttr {
+
+    @Override
+    Role getOwner();
+
+    @Override
+    RDerSchema getSchema();
 
     RDerAttrTemplate getTemplate();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RDerAttrTemplate.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RDerAttrTemplate.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RDerAttrTemplate.java
index 832d8d2..66bf7e0 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RDerAttrTemplate.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RDerAttrTemplate.java
@@ -19,8 +19,7 @@
 package org.apache.syncope.persistence.api.entity.role;
 
 import org.apache.syncope.persistence.api.entity.AttrTemplate;
-import org.apache.syncope.persistence.api.entity.DerSchema;
 
-public interface RDerAttrTemplate extends AttrTemplate<DerSchema> {
+public interface RDerAttrTemplate extends AttrTemplate<RDerSchema> {
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RDerSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RDerSchema.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RDerSchema.java
new file mode 100644
index 0000000..583c783
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RDerSchema.java
@@ -0,0 +1,25 @@
+/*
+ * 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.persistence.api.entity.role;
+
+import org.apache.syncope.persistence.api.entity.DerSchema;
+
+public interface RDerSchema extends DerSchema {
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RMappingItem.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RMappingItem.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RMappingItem.java
index 9174683..983dc18 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RMappingItem.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RMappingItem.java
@@ -18,8 +18,12 @@
  */
 package org.apache.syncope.persistence.api.entity.role;
 
+import org.apache.syncope.persistence.api.entity.Mapping;
 import org.apache.syncope.persistence.api.entity.MappingItem;
 
 public interface RMappingItem extends MappingItem {
 
+    @Override
+    Mapping<RMappingItem> getMapping();
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RNormAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RNormAttr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RNormAttr.java
deleted file mode 100644
index fed2585..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RNormAttr.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.persistence.api.entity.role;
-
-import org.apache.syncope.persistence.api.entity.NormAttr;
-
-public interface RNormAttr extends NormAttr {
-
-    RNormAttrTemplate getTemplate();
-
-    void setTemplate(RNormAttrTemplate template);
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RNormAttrTemplate.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RNormAttrTemplate.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RNormAttrTemplate.java
deleted file mode 100644
index 83f2b51..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RNormAttrTemplate.java
+++ /dev/null
@@ -1,26 +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.persistence.api.entity.role;
-
-import org.apache.syncope.persistence.api.entity.AttrTemplate;
-import org.apache.syncope.persistence.api.entity.NormSchema;
-
-public interface RNormAttrTemplate extends AttrTemplate<NormSchema> {
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RNormAttrValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RNormAttrValue.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RNormAttrValue.java
deleted file mode 100644
index cbb8e74..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RNormAttrValue.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.persistence.api.entity.role;
-
-import org.apache.syncope.persistence.api.entity.NormAttrValue;
-
-public interface RNormAttrValue extends NormAttrValue {
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainAttr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainAttr.java
new file mode 100644
index 0000000..e1cd627
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainAttr.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.persistence.api.entity.role;
+
+import java.util.List;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+
+public interface RPlainAttr extends PlainAttr {
+
+    @Override
+    Role getOwner();
+
+    @Override
+    RPlainSchema getSchema();
+
+    RPlainAttrTemplate getTemplate();
+
+    void setTemplate(RPlainAttrTemplate template);
+
+    @Override
+    List<? extends RPlainAttrValue> getValues();
+
+    @Override
+    RPlainAttrUniqueValue getUniqueValue();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainAttrTemplate.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainAttrTemplate.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainAttrTemplate.java
new file mode 100644
index 0000000..231bffe
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainAttrTemplate.java
@@ -0,0 +1,25 @@
+/*
+ * 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.persistence.api.entity.role;
+
+import org.apache.syncope.persistence.api.entity.AttrTemplate;
+
+public interface RPlainAttrTemplate extends AttrTemplate<RPlainSchema> {
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainAttrUniqueValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainAttrUniqueValue.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainAttrUniqueValue.java
new file mode 100644
index 0000000..5356ad7
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainAttrUniqueValue.java
@@ -0,0 +1,31 @@
+/*
+ * 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.persistence.api.entity.role;
+
+import org.apache.syncope.persistence.api.entity.PlainAttrUniqueValue;
+
+public interface RPlainAttrUniqueValue extends PlainAttrUniqueValue {
+
+    @Override
+    RPlainAttr getAttr();
+
+    @Override
+    RPlainSchema getSchema();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainAttrValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainAttrValue.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainAttrValue.java
new file mode 100644
index 0000000..c4d9567
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainAttrValue.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.persistence.api.entity.role;
+
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+
+public interface RPlainAttrValue extends PlainAttrValue {
+
+    @Override
+    RPlainAttr getAttr();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainSchema.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainSchema.java
new file mode 100644
index 0000000..5fc5da8
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RPlainSchema.java
@@ -0,0 +1,25 @@
+/*
+ * 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.persistence.api.entity.role;
+
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+
+public interface RPlainSchema extends PlainSchema {
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RVirAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RVirAttr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RVirAttr.java
index 1ea6519..92810fc 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RVirAttr.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RVirAttr.java
@@ -22,6 +22,12 @@ import org.apache.syncope.persistence.api.entity.VirAttr;
 
 public interface RVirAttr extends VirAttr {
 
+    @Override
+    Role getOwner();
+
+    @Override
+    RVirSchema getSchema();
+
     RVirAttrTemplate getTemplate();
 
     void setTemplate(RVirAttrTemplate template);

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RVirAttrTemplate.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RVirAttrTemplate.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RVirAttrTemplate.java
index 3e07013..c7602a4 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RVirAttrTemplate.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RVirAttrTemplate.java
@@ -19,8 +19,7 @@
 package org.apache.syncope.persistence.api.entity.role;
 
 import org.apache.syncope.persistence.api.entity.AttrTemplate;
-import org.apache.syncope.persistence.api.entity.VirSchema;
 
-public interface RVirAttrTemplate extends AttrTemplate<VirSchema> {
+public interface RVirAttrTemplate extends AttrTemplate<RVirSchema> {
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RVirSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RVirSchema.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RVirSchema.java
new file mode 100644
index 0000000..1d4cb96
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/RVirSchema.java
@@ -0,0 +1,25 @@
+/*
+ * 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.persistence.api.entity.role;
+
+import org.apache.syncope.persistence.api.entity.VirSchema;
+
+public interface RVirSchema extends VirSchema {
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/Role.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/Role.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/Role.java
index 3d314e2..0c3ac50 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/Role.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/Role.java
@@ -28,7 +28,7 @@ import org.apache.syncope.persistence.api.entity.Schema;
 import org.apache.syncope.persistence.api.entity.Subject;
 import org.apache.syncope.persistence.api.entity.user.User;
 
-public interface Role extends Subject<RNormAttr, RDerAttr, RVirAttr> {
+public interface Role extends Subject<RPlainAttr, RDerAttr, RVirAttr> {
 
     String getName();
 
@@ -43,21 +43,21 @@ public interface Role extends Subject<RNormAttr, RDerAttr, RVirAttr> {
      *
      * @return a list of inherited and only inherited attributes.
      */
-    List<RNormAttr> findLastInheritedAncestorNormAttrs();
+    List<? extends RPlainAttr> findLastInheritedAncestorPlainAttrs();
 
     /**
      * Get all inherited derived attributes from the ancestors.
      *
      * @return a list of inherited and only inherited attributes.
      */
-    List<RDerAttr> findLastInheritedAncestorDerAttrs();
+    List<? extends RDerAttr> findLastInheritedAncestorDerAttrs();
 
     /**
      * Get all inherited virtual attributes from the ancestors.
      *
      * @return a list of inherited and only inherited attributes.
      */
-    List<RVirAttr> findLastInheritedAncestorVirAttrs();
+    List<? extends RVirAttr> findLastInheritedAncestorVirAttrs();
 
     /**
      * Get first valid account policy.
@@ -74,9 +74,9 @@ public interface Role extends Subject<RNormAttr, RDerAttr, RVirAttr> {
 
     <T extends AttrTemplate<K>, K extends Schema> List<K> getAttrTemplateSchemas(Class<T> reference);
 
-    <T extends AttrTemplate<Schema>> List<T> getAttrTemplates(Class<T> reference);
+    <T extends AttrTemplate<K>, K extends Schema> List<T> getAttrTemplates(Class<T> reference);
 
-    Set<Entitlement> getEntitlements();
+    Set<? extends Entitlement> getEntitlements();
 
     /**
      * Get first valid password policy.
@@ -106,8 +106,6 @@ public interface Role extends Subject<RNormAttr, RDerAttr, RVirAttr> {
 
     void setAccountPolicy(AccountPolicy accountPolicy);
 
-    void setEntitlements(List<Entitlement> entitlements);
-
     void setInheritAccountPolicy(boolean condition);
 
     void setInheritAttrs(boolean inheritAttrs);
@@ -133,7 +131,7 @@ public interface Role extends Subject<RNormAttr, RDerAttr, RVirAttr> {
     void setUserOwner(User userOwner);
 
     @Override
-    boolean addNormAttr(RNormAttr attr);
+    boolean addPlainAttr(RPlainAttr attr);
 
     @Override
     boolean addDerAttr(RDerAttr attr);
@@ -142,25 +140,25 @@ public interface Role extends Subject<RNormAttr, RDerAttr, RVirAttr> {
     boolean addVirAttr(RVirAttr attr);
 
     @Override
-    RNormAttr getNormAttr(String normSchemaName);
+    RPlainAttr getPlainAttr(String plainSchemaName);
 
     @Override
-    List<RNormAttr> getNormAttrs();
+    List<? extends RPlainAttr> getPlainAttrs();
 
     @Override
     RDerAttr getDerAttr(String derSchemaName);
 
     @Override
-    List<RDerAttr> getDerAttrs();
+    List<? extends RDerAttr> getDerAttrs();
 
     @Override
     RVirAttr getVirAttr(String virSchemaName);
 
     @Override
-    List<RVirAttr> getVirAttrs();
+    List<? extends RVirAttr> getVirAttrs();
 
     @Override
-    boolean removeNormAttr(RNormAttr attr);
+    boolean removePlainAttr(RPlainAttr attr);
 
     @Override
     boolean removeDerAttr(RDerAttr derAttr);

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/NotificationTask.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/NotificationTask.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/NotificationTask.java
index a60ee2b..07c3744 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/NotificationTask.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/NotificationTask.java
@@ -45,8 +45,6 @@ public interface NotificationTask extends Task {
 
     boolean removeRecipient(String recipient);
 
-    void setRecipients(Set<String> recipients);
-
     void setSender(String sender);
 
     void setSubject(String subject);

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/SyncTask.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/SyncTask.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/SyncTask.java
index e51f379..1cf1e35 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/SyncTask.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/SyncTask.java
@@ -18,17 +18,20 @@
  */
 package org.apache.syncope.persistence.api.entity.task;
 
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.to.UserTO;
+
 public interface SyncTask extends ProvisioningTask {
 
-    String getRoleTemplate();
+    RoleTO getRoleTemplate();
 
-    String getUserTemplate();
+    UserTO getUserTemplate();
 
     boolean isFullReconciliation();
 
     void setFullReconciliation(boolean condition);
 
-    void setRoleTemplate(String roleTemplate);
+    void setRoleTemplate(RoleTO roleTemplate);
 
-    void setUserTemplate(String userTemplate);
+    void setUserTemplate(UserTO userTemplate);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/Task.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/Task.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/Task.java
index baf8637..7c7c005 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/Task.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/Task.java
@@ -19,15 +19,16 @@
 package org.apache.syncope.persistence.api.entity.task;
 
 import java.util.List;
+import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.persistence.api.entity.Entity;
 
 public interface Task extends Entity<Long> {
 
+    TaskType getType();
+
     boolean addExec(TaskExec exec);
 
     boolean removeExec(TaskExec exec);
 
-    List<TaskExec> getExecs();
-
-    void setExecs(List<TaskExec> executions);
+    List<? extends TaskExec> getExecs();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UDerAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UDerAttr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UDerAttr.java
index ffec8ba..5c5e52d 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UDerAttr.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UDerAttr.java
@@ -20,6 +20,12 @@ package org.apache.syncope.persistence.api.entity.user;
 
 import org.apache.syncope.persistence.api.entity.DerAttr;
 
-public interface UDerAttr extends DerAttr<UNormAttr> {
+public interface UDerAttr extends DerAttr {
+
+    @Override
+    User getOwner();
+
+    @Override
+    UDerSchema getSchema();
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UDerSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UDerSchema.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UDerSchema.java
new file mode 100644
index 0000000..7ab8cb1
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UDerSchema.java
@@ -0,0 +1,25 @@
+/*
+ * 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.persistence.api.entity.user;
+
+import org.apache.syncope.persistence.api.entity.DerSchema;
+
+public interface UDerSchema extends DerSchema {
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UMappingItem.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UMappingItem.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UMappingItem.java
index e14eefe..2352130 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UMappingItem.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UMappingItem.java
@@ -18,8 +18,12 @@
  */
 package org.apache.syncope.persistence.api.entity.user;
 
+import org.apache.syncope.persistence.api.entity.Mapping;
 import org.apache.syncope.persistence.api.entity.MappingItem;
 
 public interface UMappingItem extends MappingItem {
 
+    @Override
+    Mapping<UMappingItem> getMapping();
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UNormAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UNormAttr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UNormAttr.java
deleted file mode 100644
index ed0ea4a..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UNormAttr.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.persistence.api.entity.user;
-
-import org.apache.syncope.persistence.api.entity.NormAttr;
-
-public interface UNormAttr extends NormAttr {
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UNormAttrValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UNormAttrValue.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UNormAttrValue.java
deleted file mode 100644
index 2340fb8..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UNormAttrValue.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.persistence.api.entity.user;
-
-import org.apache.syncope.persistence.api.entity.NormAttrValue;
-
-public interface UNormAttrValue extends NormAttrValue {
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UPlainAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UPlainAttr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UPlainAttr.java
new file mode 100644
index 0000000..59a9863
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UPlainAttr.java
@@ -0,0 +1,38 @@
+/*
+ * 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.persistence.api.entity.user;
+
+import java.util.List;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+
+public interface UPlainAttr extends PlainAttr {
+
+    @Override
+    User getOwner();
+
+    @Override
+    UPlainSchema getSchema();
+
+    @Override
+    List<? extends UPlainAttrValue> getValues();
+
+    @Override
+    UPlainAttrUniqueValue getUniqueValue();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UPlainAttrUniqueValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UPlainAttrUniqueValue.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UPlainAttrUniqueValue.java
new file mode 100644
index 0000000..078da52
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UPlainAttrUniqueValue.java
@@ -0,0 +1,31 @@
+/*
+ * 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.persistence.api.entity.user;
+
+import org.apache.syncope.persistence.api.entity.PlainAttrUniqueValue;
+
+public interface UPlainAttrUniqueValue extends PlainAttrUniqueValue {
+
+    @Override
+    UPlainAttr getAttr();
+
+    @Override
+    UPlainSchema getSchema();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UPlainAttrValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UPlainAttrValue.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UPlainAttrValue.java
new file mode 100644
index 0000000..bab1fde
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UPlainAttrValue.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.persistence.api.entity.user;
+
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+
+public interface UPlainAttrValue extends PlainAttrValue {
+
+    @Override
+    UPlainAttr getAttr();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UPlainSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UPlainSchema.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UPlainSchema.java
new file mode 100644
index 0000000..1ec236e
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UPlainSchema.java
@@ -0,0 +1,25 @@
+/*
+ * 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.persistence.api.entity.user;
+
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+
+public interface UPlainSchema extends PlainSchema {
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UVirAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UVirAttr.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UVirAttr.java
index baf744d..78f6882 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UVirAttr.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UVirAttr.java
@@ -22,4 +22,10 @@ import org.apache.syncope.persistence.api.entity.VirAttr;
 
 public interface UVirAttr extends VirAttr {
 
+    @Override
+    User getOwner();
+
+    @Override
+    UVirSchema getSchema();
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UVirSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UVirSchema.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UVirSchema.java
new file mode 100644
index 0000000..78575f7
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/UVirSchema.java
@@ -0,0 +1,25 @@
+/*
+ * 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.persistence.api.entity.user;
+
+import org.apache.syncope.persistence.api.entity.VirSchema;
+
+public interface UVirSchema extends VirSchema {
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/User.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/User.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/User.java
index c7aaf9f..6eece4d 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/User.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/user/User.java
@@ -27,7 +27,7 @@ import org.apache.syncope.persistence.api.entity.Subject;
 import org.apache.syncope.persistence.api.entity.membership.Membership;
 import org.apache.syncope.persistence.api.entity.role.Role;
 
-public interface User extends Subject<UNormAttr, UDerAttr, UVirAttr> {
+public interface User extends Subject<UPlainAttr, UDerAttr, UVirAttr> {
 
     boolean addMembership(Membership membership);
 
@@ -49,9 +49,9 @@ public interface User extends Subject<UNormAttr, UDerAttr, UVirAttr> {
 
     Membership getMembership(Long syncopeRoleId);
 
-    List<Membership> getMemberships();
+    List<? extends Membership> getMemberships();
 
-    Set<ExternalResource> getOwnResources();
+    Set<? extends ExternalResource> getOwnResources();
 
     String getPassword();
 
@@ -95,8 +95,6 @@ public interface User extends Subject<UNormAttr, UDerAttr, UVirAttr> {
 
     void setLastLoginDate(Date lastLoginDate);
 
-    void setMemberships(List<Membership> memberships);
-
     void setPassword(String password, CipherAlgorithm cipherAlgoritm);
 
     void setSecurityAnswer(String securityAnswer);
@@ -114,39 +112,39 @@ public interface User extends Subject<UNormAttr, UDerAttr, UVirAttr> {
     boolean verifyPasswordHistory(String password, int size);
 
     @Override
-    boolean addNormAttr(UNormAttr attr);
+    boolean addPlainAttr(UPlainAttr attr);
 
     @Override
-    boolean addDerAttr(UDerAttr attr);
+    boolean removePlainAttr(UPlainAttr attr);
 
     @Override
-    boolean addVirAttr(UVirAttr attr);
+    boolean addDerAttr(UDerAttr attr);
 
     @Override
-    UNormAttr getNormAttr(String normSchemaName);
+    boolean removeDerAttr(UDerAttr derAttr);
 
     @Override
-    List<UNormAttr> getNormAttrs();
+    boolean addVirAttr(UVirAttr attr);
 
     @Override
-    UDerAttr getDerAttr(String derSchemaName);
+    boolean removeVirAttr(UVirAttr virAttr);
 
     @Override
-    List<UDerAttr> getDerAttrs();
+    UPlainAttr getPlainAttr(String plainSchemaName);
 
     @Override
-    UVirAttr getVirAttr(String virSchemaName);
+    List<? extends UPlainAttr> getPlainAttrs();
 
     @Override
-    List<UVirAttr> getVirAttrs();
+    UDerAttr getDerAttr(String derSchemaName);
 
     @Override
-    boolean removeNormAttr(UNormAttr attr);
+    List<? extends UDerAttr> getDerAttrs();
 
     @Override
-    boolean removeDerAttr(UDerAttr derAttr);
+    UVirAttr getVirAttr(String virSchemaName);
 
     @Override
-    boolean removeVirAttr(UVirAttr virAttr);
+    List<? extends UVirAttr> getVirAttrs();
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/pom.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/pom.xml b/syncope620/server/persistence-jpa/pom.xml
new file mode 100644
index 0000000..17b6a92
--- /dev/null
+++ b/syncope620/server/persistence-jpa/pom.xml
@@ -0,0 +1,224 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.syncope</groupId>
+    <artifactId>syncope-server</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Server Persistence JPA</name>
+  <description>Apache Syncope Server Persistence JPA</description>
+  <groupId>org.apache.syncope.server</groupId>
+  <artifactId>syncope-persistence-jpa</artifactId>
+  <packaging>jar</packaging>
+
+  <dependencies>    
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-jpa_2.0_spec</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>javax.el</groupId>
+      <artifactId>javax.el-api</artifactId>
+    </dependency>
+      
+    <dependency>
+      <groupId>org.apache.openjpa</groupId>
+      <artifactId>openjpa-jdbc</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.openjpa</groupId>
+      <artifactId>openjpa-persistence-jdbc</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-dbcp2</artifactId>
+    </dependency>
+      
+    <dependency>
+      <groupId>org.hibernate</groupId>
+      <artifactId>hibernate-validator</artifactId>
+    </dependency>
+      
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-tx</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-jdbc</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-orm</artifactId>
+    </dependency>
+      
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+    </dependency>
+            
+    <dependency>
+      <groupId>org.quartz-scheduler</groupId>
+      <artifactId>quartz</artifactId>
+    </dependency>
+      
+    <dependency>
+      <groupId>org.apache.syncope.server</groupId>
+      <artifactId>syncope-provisioning-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.server</groupId>
+      <artifactId>syncope-persistence-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.server</groupId>
+      <artifactId>syncope-server-utils</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.server</groupId>
+      <artifactId>syncope-server-spring</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.server</groupId>
+      <artifactId>syncope-server-security</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    
+    <!-- TEST -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <version>${slf4j.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.h2database</groupId>
+      <artifactId>h2</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.openjpa</groupId>
+        <artifactId>openjpa-maven-plugin</artifactId>
+        <inherited>true</inherited>
+        <dependencies>
+          <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+            <version>${h2.version}</version>
+          </dependency>
+        </dependencies>
+        <configuration>
+          <persistenceXmlFile>${project.basedir}/src/main/resources/META-INF/spring-persistence.xml</persistenceXmlFile> 
+          <includes>org/apache/syncope/persistence/jpa/entity/**/*.class</includes>
+          <connectionDriverName>org.springframework.jdbc.datasource.DriverManagerDataSource</connectionDriverName>
+          <connectionProperties>
+            driverClassName=org.h2.Driver,
+            url=jdbc:h2:mem:syncopedb
+            username=sa,
+            password=
+          </connectionProperties>
+        </configuration>
+        <executions>
+          <execution>
+            <id>enhancer</id>
+            <phase>process-classes</phase>
+            <goals>
+              <goal>enhance</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+        <filtering>true</filtering>
+      </resource>
+    </resources>
+    <testResources>
+      <testResource>
+        <directory>src/test/resources</directory>
+        <filtering>true</filtering>        
+      </testResource>
+    </testResources>
+  </build>
+
+  <profiles>
+    <profile>
+      <id>sqlgen</id>
+      
+      <properties>
+        <skipTests>true</skipTests>
+      </properties>
+      
+      <build>
+        <defaultGoal>clean verify</defaultGoal>
+        
+        <plugins>
+          <plugin>
+            <groupId>org.apache.openjpa</groupId>
+            <artifactId>openjpa-maven-plugin</artifactId>
+            <inherited>true</inherited>
+            <executions>
+              <execution>
+                <id>sqlgenr</id>
+                <phase>process-classes</phase>
+                <goals>
+                  <goal>sql</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>          
+        </plugins>
+      </build>
+        
+    </profile>
+  </profiles>
+
+</project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/attrvalue/validation/AbstractValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/attrvalue/validation/AbstractValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/attrvalue/validation/AbstractValidator.java
new file mode 100644
index 0000000..637f923
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/attrvalue/validation/AbstractValidator.java
@@ -0,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.persistence.jpa.attrvalue.validation;
+
+import java.io.Serializable;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidPlainAttrValueException;
+import org.apache.syncope.persistence.api.attrvalue.validation.ParsingValidationException;
+import org.apache.syncope.persistence.api.attrvalue.validation.Validator;
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractValidator implements Validator, Serializable {
+
+    private static final long serialVersionUID = -5439345166669502493L;
+
+    /*
+     * Logger
+     */
+    protected static final Logger LOG = LoggerFactory.getLogger(AbstractValidator.class);
+
+    protected final PlainSchema schema;
+
+    public AbstractValidator(final PlainSchema schema) {
+        this.schema = schema;
+    }
+
+    @Override
+    public void validate(String value, PlainAttrValue attrValue)
+            throws ParsingValidationException, InvalidPlainAttrValueException {
+
+        attrValue.parseValue(schema, value);
+        doValidate(attrValue);
+    }
+
+    protected abstract void doValidate(PlainAttrValue attrValue) throws InvalidPlainAttrValueException;
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/attrvalue/validation/AlwaysTrueValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/attrvalue/validation/AlwaysTrueValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/attrvalue/validation/AlwaysTrueValidator.java
new file mode 100644
index 0000000..919da6d
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/attrvalue/validation/AlwaysTrueValidator.java
@@ -0,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.persistence.jpa.attrvalue.validation;
+
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidPlainAttrValueException;
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+
+public class AlwaysTrueValidator extends AbstractValidator {
+
+    private static final long serialVersionUID = 872107345555773183L;
+
+    public AlwaysTrueValidator(final PlainSchema schema) {
+        super(schema);
+    }
+
+    @Override
+    protected void doValidate(final PlainAttrValue attrValue) throws InvalidPlainAttrValueException {
+        Boolean value = attrValue.getValue();
+        if (!value) {
+            throw new InvalidPlainAttrValueException("This attribute must be set to \"true\"");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/attrvalue/validation/BasicValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/attrvalue/validation/BasicValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/attrvalue/validation/BasicValidator.java
new file mode 100644
index 0000000..a2b9731
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/attrvalue/validation/BasicValidator.java
@@ -0,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.persistence.jpa.attrvalue.validation;
+
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidPlainAttrValueException;
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+
+public class BasicValidator extends AbstractValidator {
+
+    private static final long serialVersionUID = -2606728447694223607L;
+
+    public BasicValidator(final PlainSchema schema) {
+        super(schema);
+    }
+
+    @Override
+    protected void doValidate(final PlainAttrValue attrValue) throws InvalidPlainAttrValueException {
+        if (AttrSchemaType.Enum == schema.getType()) {
+            final String[] enumeration = schema.getEnumerationValues().split(SyncopeConstants.ENUM_VALUES_SEPARATOR);
+            final String value = attrValue.getStringValue();
+
+            boolean found = false;
+            for (int i = 0; i < enumeration.length && !found; i++) {
+                if (enumeration[i].trim().equals(value)) {
+                    found = true;
+                }
+            }
+
+            if (!found) {
+                throw new InvalidPlainAttrValueException(
+                        "'" + value + "' is not one of: " + schema.getEnumerationValues());
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/attrvalue/validation/EmailAddressValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/attrvalue/validation/EmailAddressValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/attrvalue/validation/EmailAddressValidator.java
new file mode 100644
index 0000000..d334b65
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/attrvalue/validation/EmailAddressValidator.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.persistence.jpa.attrvalue.validation;
+
+import java.util.regex.Matcher;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidPlainAttrValueException;
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+
+public class EmailAddressValidator extends AbstractValidator {
+
+    private static final long serialVersionUID = 792457177290331518L;
+
+    public EmailAddressValidator(final PlainSchema schema) {
+        super(schema);
+    }
+
+    @Override
+    protected void doValidate(final PlainAttrValue attrValue) throws InvalidPlainAttrValueException {
+        Matcher matcher = SyncopeConstants.EMAIL_PATTERN.matcher(attrValue.<CharSequence>getValue());
+        if (!matcher.matches()) {
+            throw new InvalidPlainAttrValueException("\"" + attrValue.getValue() + "\" is not a valid email address");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/content/AbstractContentDealer.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/content/AbstractContentDealer.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/content/AbstractContentDealer.java
new file mode 100644
index 0000000..e3ad2d4
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/content/AbstractContentDealer.java
@@ -0,0 +1,88 @@
+/*
+ * 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.persistence.jpa.content;
+
+import java.io.IOException;
+import java.util.Properties;
+import javax.annotation.Resource;
+import javax.sql.DataSource;
+import org.apache.syncope.server.spring.ResourceWithFallbackLoader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.support.PropertiesLoaderUtils;
+import org.springframework.dao.DataAccessException;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+public abstract class AbstractContentDealer {
+
+    protected static final Logger LOG = LoggerFactory.getLogger(AbstractContentDealer.class);
+
+    protected static final String ROOT_ELEMENT = "dataset";
+
+    @Resource(name = "database.schema")
+    protected String dbSchema;
+
+    @Resource(name = "indexesXML")
+    private ResourceWithFallbackLoader indexesXML;
+
+    @Resource(name = "viewsXML")
+    private ResourceWithFallbackLoader viewsXML;
+
+    @Autowired
+    protected DataSource dataSource;
+
+    protected void createIndexes() throws IOException {
+        LOG.debug("Creating indexes");
+
+        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
+
+        Properties indexes = PropertiesLoaderUtils.loadProperties(indexesXML.getResource());
+        for (String idx : indexes.stringPropertyNames()) {
+            LOG.debug("Creating index {}", indexes.get(idx).toString());
+
+            try {
+                jdbcTemplate.execute(indexes.get(idx).toString());
+            } catch (DataAccessException e) {
+                LOG.error("Could not create index ", e);
+            }
+        }
+
+        LOG.debug("Indexes created");
+    }
+
+    protected void createViews() throws IOException {
+        LOG.debug("Creating views");
+
+        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
+
+        Properties views = PropertiesLoaderUtils.loadProperties(viewsXML.getResource());
+        for (String idx : views.stringPropertyNames()) {
+            LOG.debug("Creating view {}", views.get(idx).toString());
+
+            try {
+                jdbcTemplate.execute(views.get(idx).toString().replaceAll("\\n", " "));
+            } catch (DataAccessException e) {
+                LOG.error("Could not create view ", e);
+            }
+        }
+
+        LOG.debug("Views created");
+    }
+}


[28/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/content/ContentLoaderHandler.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/content/ContentLoaderHandler.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/content/ContentLoaderHandler.java
new file mode 100644
index 0000000..2b3bd4a
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/content/ContentLoaderHandler.java
@@ -0,0 +1,199 @@
+/*
+ * 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.persistence.jpa.content;
+
+import org.apache.syncope.server.utils.DataFormat;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.text.ParseException;
+import java.util.HashMap;
+import java.util.Map;
+import javax.sql.DataSource;
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.dao.DataAccessException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.ResultSetExtractor;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * SAX handler for generating SQL INSERT statements out of given XML file.
+ */
+class ContentLoaderHandler extends DefaultHandler {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ContentLoaderHandler.class);
+
+    private final DataSource dataSource;
+
+    private final String rootElement;
+
+    public ContentLoaderHandler(final DataSource dataSource, final String rootElement) {
+        this.dataSource = dataSource;
+        this.rootElement = rootElement;
+    }
+
+    private Object[] getParameters(final String tableName, final Attributes attrs) {
+        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
+
+        Map<String, Integer> colTypes = jdbcTemplate.query("SELECT * FROM " + tableName,
+                new ResultSetExtractor<Map<String, Integer>>() {
+
+                    @Override
+                    public Map<String, Integer> extractData(final ResultSet rs) throws SQLException, DataAccessException {
+                        Map<String, Integer> colTypes = new HashMap<String, Integer>();
+                        for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
+                            colTypes.put(rs.getMetaData().getColumnName(i).toUpperCase(),
+                                    rs.getMetaData().getColumnType(i));
+                        }
+                        return colTypes;
+                    }
+                });
+
+        Object[] parameters = new Object[attrs.getLength()];
+        for (int i = 0; i < attrs.getLength(); i++) {
+            Integer colType = colTypes.get(attrs.getQName(i).toUpperCase());
+            if (colType == null) {
+                LOG.warn("No column type found for {}", attrs.getQName(i).toUpperCase());
+                colType = Types.VARCHAR;
+            }
+
+            switch (colType) {
+                case Types.INTEGER:
+                case Types.TINYINT:
+                case Types.SMALLINT:
+                    try {
+                        parameters[i] = Integer.valueOf(attrs.getValue(i));
+                    } catch (NumberFormatException e) {
+                        LOG.error("Unparsable Integer '{}'", attrs.getValue(i));
+                        parameters[i] = attrs.getValue(i);
+                    }
+                    break;
+
+                case Types.NUMERIC:
+                case Types.DECIMAL:
+                case Types.BIGINT:
+                    try {
+                        parameters[i] = Long.valueOf(attrs.getValue(i));
+                    } catch (NumberFormatException e) {
+                        LOG.error("Unparsable Long '{}'", attrs.getValue(i));
+                        parameters[i] = attrs.getValue(i);
+                    }
+                    break;
+
+                case Types.DOUBLE:
+                    try {
+                        parameters[i] = Double.valueOf(attrs.getValue(i));
+                    } catch (NumberFormatException e) {
+                        LOG.error("Unparsable Double '{}'", attrs.getValue(i));
+                        parameters[i] = attrs.getValue(i);
+                    }
+                    break;
+
+                case Types.REAL:
+                case Types.FLOAT:
+                    try {
+                        parameters[i] = Float.valueOf(attrs.getValue(i));
+                    } catch (NumberFormatException e) {
+                        LOG.error("Unparsable Float '{}'", attrs.getValue(i));
+                        parameters[i] = attrs.getValue(i);
+                    }
+                    break;
+
+                case Types.DATE:
+                case Types.TIME:
+                case Types.TIMESTAMP:
+                    try {
+                        parameters[i] = DataFormat.parseDate(attrs.getValue(i));
+                    } catch (ParseException e) {
+                        LOG.error("Unparsable Date '{}'", attrs.getValue(i));
+                        parameters[i] = attrs.getValue(i);
+                    }
+                    break;
+
+                case Types.BIT:
+                case Types.BOOLEAN:
+                    parameters[i] = "1".equals(attrs.getValue(i)) ? Boolean.TRUE : Boolean.FALSE;
+                    break;
+
+                case Types.BINARY:
+                case Types.VARBINARY:
+                case Types.LONGVARBINARY:
+                    try {
+                        parameters[i] = Hex.decodeHex(attrs.getValue(i).toCharArray());
+                    } catch (DecoderException | IllegalArgumentException e) {
+                        parameters[i] = attrs.getValue(i);
+                    }
+                    break;
+
+                case Types.BLOB:
+                    try {
+                        parameters[i] = Hex.decodeHex(attrs.getValue(i).toCharArray());
+                    } catch (DecoderException | IllegalArgumentException e) {
+                        LOG.warn("Error decoding hex string to specify a blob parameter", e);
+                        parameters[i] = attrs.getValue(i);
+                    } catch (Exception e) {
+                        LOG.warn("Error creating a new blob parameter", e);
+                    }
+                    break;
+
+                default:
+                    parameters[i] = attrs.getValue(i);
+            }
+        }
+
+        return parameters;
+    }
+
+    @Override
+    public void startElement(final String uri, final String localName, final String qName, final Attributes atts)
+            throws SAXException {
+
+        // skip root element
+        if (rootElement.equals(qName)) {
+            return;
+        }
+
+        StringBuilder query = new StringBuilder("INSERT INTO ").append(qName).append('(');
+
+        StringBuilder values = new StringBuilder();
+
+        for (int i = 0; i < atts.getLength(); i++) {
+            query.append(atts.getQName(i));
+            values.append('?');
+            if (i < atts.getLength() - 1) {
+                query.append(',');
+                values.append(',');
+            }
+        }
+        query.append(") VALUES (").append(values).append(')');
+
+        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
+
+        try {
+            jdbcTemplate.update(query.toString(), getParameters(qName, atts));
+        } catch (DataAccessException e) {
+            LOG.error("While trying to perform {}", query, e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/content/XMLContentLoader.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/content/XMLContentLoader.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/content/XMLContentLoader.java
new file mode 100644
index 0000000..e222501
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/content/XMLContentLoader.java
@@ -0,0 +1,89 @@
+/*
+ * 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.persistence.jpa.content;
+
+import java.io.IOException;
+import java.io.InputStream;
+import javax.annotation.Resource;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import org.apache.commons.io.IOUtils;
+import org.apache.syncope.persistence.api.content.ContentLoader;
+import org.apache.syncope.persistence.jpa.entity.conf.JPAConf;
+import org.apache.syncope.server.spring.ResourceWithFallbackLoader;
+import org.springframework.dao.DataAccessException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * Initialize Database with default content if no data is present already.
+ */
+@Component
+public class XMLContentLoader extends AbstractContentDealer implements ContentLoader {
+
+    @Resource(name = "contentXML")
+    private ResourceWithFallbackLoader contentXML;
+
+    @Transactional
+    @Override
+    public void load() {
+        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
+
+        boolean existingData;
+        try {
+            existingData = jdbcTemplate.queryForObject("SELECT COUNT(0) FROM " + JPAConf.TABLE, Integer.class) > 0;
+        } catch (DataAccessException e) {
+            LOG.error("Could not access to table " + JPAConf.TABLE, e);
+            existingData = true;
+        }
+
+        if (existingData) {
+            LOG.info("Data found in the database, leaving untouched");
+        } else {
+            LOG.info("Empty database found, loading default content");
+
+            try {
+                loadDefaultContent();
+            } catch (Exception e) {
+                LOG.error("While loading default content", e);
+            }
+            try {
+                createIndexes();
+                createViews();
+            } catch (IOException e) {
+                LOG.error("While creating indexes and views", e);
+            }
+        }
+    }
+
+    private void loadDefaultContent() throws Exception {
+        SAXParserFactory factory = SAXParserFactory.newInstance();
+        InputStream in = null;
+        try {
+            in = contentXML.getResource().getInputStream();
+
+            SAXParser parser = factory.newSAXParser();
+            parser.parse(in, new ContentLoaderHandler(dataSource, ROOT_ELEMENT));
+            LOG.debug("Default content successfully loaded");
+        } finally {
+            IOUtils.closeQuietly(in);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/AbstractDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/AbstractDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/AbstractDAO.java
new file mode 100644
index 0000000..b7b1f5d
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/AbstractDAO.java
@@ -0,0 +1,117 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.List;
+import javax.persistence.CacheRetrieveMode;
+import javax.persistence.CacheStoreMode;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.PersistenceContextType;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.persistence.api.dao.DAO;
+import org.apache.syncope.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.persistence.api.entity.Entity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Configurable;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.util.ReflectionUtils;
+
+@Configurable
+public abstract class AbstractDAO<E extends Entity<KEY>, KEY> implements DAO<E, KEY> {
+
+    /**
+     * Logger.
+     */
+    protected static final Logger LOG = LoggerFactory.getLogger(DAO.class);
+
+    private static final String CACHE_STORE_MODE = "javax.persistence.cache.storeMode";
+
+    private static final String CACHE_RETRIEVE_MODE = "javax.persistence.cache.retrieveMode";
+
+    @Value("#{entityManager}")
+    @PersistenceContext(type = PersistenceContextType.TRANSACTION)
+    protected EntityManager entityManager;
+
+    protected CacheRetrieveMode getCacheRetrieveMode() {
+        return entityManager.getProperties().containsKey(CACHE_RETRIEVE_MODE)
+                ? (CacheRetrieveMode) entityManager.getProperties().get(CACHE_RETRIEVE_MODE)
+                : CacheRetrieveMode.BYPASS;
+    }
+
+    protected void setCacheRetrieveMode(final CacheRetrieveMode retrieveMode) {
+        if (retrieveMode != null) {
+            entityManager.getProperties().put(CACHE_RETRIEVE_MODE, retrieveMode);
+        }
+    }
+
+    protected CacheStoreMode getCacheStoreMode() {
+        return entityManager.getProperties().containsKey(CACHE_STORE_MODE)
+                ? (CacheStoreMode) entityManager.getProperties().get(CACHE_STORE_MODE)
+                : CacheStoreMode.BYPASS;
+    }
+
+    protected void setCacheStoreMode(final CacheStoreMode storeMode) {
+        if (storeMode != null) {
+            entityManager.getProperties().put(CACHE_STORE_MODE, storeMode);
+        }
+    }
+
+    protected String toOrderByStatement(final Class<? extends Entity<KEY>> beanClass, final String prefix,
+            final List<OrderByClause> orderByClauses) {
+
+        StringBuilder statement = new StringBuilder();
+
+        for (OrderByClause clause : orderByClauses) {
+            String field = clause.getField().trim();
+            if (ReflectionUtils.findField(beanClass, field) != null) {
+                if (StringUtils.isNotBlank(prefix)) {
+                    statement.append(prefix).append('.');
+                }
+                statement.append(field).append(' ').append(clause.getDirection().name());
+            }
+        }
+
+        if (statement.length() > 0) {
+            statement.insert(0, "ORDER BY ");
+        }
+        return statement.toString();
+    }
+
+    @Override
+    public void refresh(final E entity) {
+        entityManager.refresh(entity);
+    }
+
+    @Override
+    public void detach(final E entity) {
+        entityManager.detach(entity);
+    }
+
+    @Override
+    public void flush() {
+        entityManager.flush();
+    }
+
+    @Override
+    public void clear() {
+        entityManager.clear();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/AbstractSubjectDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/AbstractSubjectDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/AbstractSubjectDAO.java
new file mode 100644
index 0000000..53b2cc4
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/AbstractSubjectDAO.java
@@ -0,0 +1,349 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import static org.apache.syncope.common.lib.types.AttrSchemaType.Double;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+import javax.persistence.Query;
+import javax.persistence.TemporalType;
+import org.apache.commons.jexl2.parser.Parser;
+import org.apache.commons.jexl2.parser.ParserConstants;
+import org.apache.commons.jexl2.parser.Token;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.persistence.api.dao.DerSchemaDAO;
+import org.apache.syncope.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.persistence.api.dao.SubjectDAO;
+import org.apache.syncope.persistence.api.entity.AttributableUtil;
+import org.apache.syncope.persistence.api.entity.DerAttr;
+import org.apache.syncope.persistence.api.entity.DerSchema;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.apache.syncope.persistence.api.entity.Subject;
+import org.apache.syncope.persistence.api.entity.VirAttr;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainAttrValue;
+import org.springframework.beans.factory.annotation.Autowired;
+
+abstract class AbstractSubjectDAO<P extends PlainAttr, D extends DerAttr, V extends VirAttr>
+        extends AbstractDAO<Subject<P, D, V>, Long> implements SubjectDAO<P, D, V> {
+
+    @Autowired
+    protected PlainSchemaDAO plainSchemaDAO;
+
+    @Autowired
+    protected DerSchemaDAO derSchemaDAO;
+
+    /**
+     * Split an attribute value recurring on provided literals/tokens.
+     *
+     * @param attrValue value to be split
+     * @param literals literals/tokens
+     * @return split value
+     */
+    private List<String> split(final String attrValue, final List<String> literals) {
+        final List<String> attrValues = new ArrayList<>();
+
+        if (literals.isEmpty()) {
+            attrValues.add(attrValue);
+        } else {
+            for (String token : attrValue.split(Pattern.quote(literals.get(0)))) {
+                attrValues.addAll(split(token, literals.subList(1, literals.size())));
+            }
+        }
+
+        return attrValues;
+    }
+
+    /**
+     * Generate one where clause for each different attribute schema into the derived schema expression provided.
+     *
+     * @param expression derived schema expression
+     * @param value derived attribute value
+     * @param attrUtil USER / ROLE
+     * @return where clauses to use to build the query
+     */
+    private Set<String> getWhereClause(final String expression, final String value, final AttributableUtil attrUtil) {
+        final Parser parser = new Parser(new StringReader(expression));
+
+        // Schema names
+        final List<String> identifiers = new ArrayList<String>();
+
+        // Literals
+        final List<String> literals = new ArrayList<String>();
+
+        // Get schema names and literals
+        Token token;
+        while ((token = parser.getNextToken()) != null && StringUtils.isNotBlank(token.toString())) {
+            if (token.kind == ParserConstants.STRING_LITERAL) {
+                literals.add(token.toString().substring(1, token.toString().length() - 1));
+            }
+
+            if (token.kind == ParserConstants.IDENTIFIER) {
+                identifiers.add(token.toString());
+            }
+        }
+
+        // Sort literals in order to process later literals included into others
+        Collections.sort(literals, new Comparator<String>() {
+
+            @Override
+            public int compare(final String t, final String t1) {
+                if (t == null && t1 == null) {
+                    return 0;
+                } else if (t != null && t1 == null) {
+                    return -1;
+                } else if (t == null && t1 != null) {
+                    return 1;
+                } else if (t.length() == t1.length()) {
+                    return 0;
+                } else if (t.length() > t1.length()) {
+                    return -1;
+                } else {
+                    return 1;
+                }
+            }
+        });
+
+        // Split value on provided literals
+        final List<String> attrValues = split(value, literals);
+
+        if (attrValues.size() != identifiers.size()) {
+            LOG.error("Ambiguous jexl expression resolution.");
+            throw new IllegalArgumentException("literals and values have different size");
+        }
+
+        // clauses to be used with INTERSECTed queries
+        final Set<String> clauses = new HashSet<String>();
+
+        // builder to build the clauses
+        final StringBuilder bld = new StringBuilder();
+
+        // Contains used identifiers in order to avoid replications
+        final Set<String> used = new HashSet<String>();
+
+        // Create several clauses: one for eanch identifiers
+        for (int i = 0; i < identifiers.size(); i++) {
+            if (!used.contains(identifiers.get(i))) {
+
+                // verify schema existence and get schema type
+                PlainSchema schema = plainSchemaDAO.find(identifiers.get(i), attrUtil.plainSchemaClass());
+                if (schema == null) {
+                    LOG.error("Invalid schema name '{}'", identifiers.get(i));
+                    throw new IllegalArgumentException("Invalid schema name " + identifiers.get(i));
+                }
+
+                // clear builder
+                bld.delete(0, bld.length());
+
+                bld.append("(");
+
+                // set schema name
+                bld.append("s.name = '").append(identifiers.get(i)).append("'");
+
+                bld.append(" AND ");
+
+                bld.append("s.name = a.schema_name").append(" AND ");
+
+                bld.append("a.id = v.attribute_id");
+
+                bld.append(" AND ");
+
+                // use a value clause different for eanch different schema type
+                switch (schema.getType()) {
+                    case Boolean:
+                        bld.append("v.booleanValue = '").append(attrValues.get(i)).append("'");
+                        break;
+                    case Long:
+                        bld.append("v.longValue = ").append(attrValues.get(i));
+                        break;
+                    case Double:
+                        bld.append("v.doubleValue = ").append(attrValues.get(i));
+                        break;
+                    case Date:
+                        bld.append("v.dateValue = '").append(attrValues.get(i)).append("'");
+                        break;
+                    default:
+                        bld.append("v.stringValue = '").append(attrValues.get(i)).append("'");
+                }
+
+                bld.append(")");
+
+                used.add(identifiers.get(i));
+
+                clauses.add(bld.toString());
+            }
+        }
+
+        LOG.debug("Generated where clauses {}", clauses);
+
+        return clauses;
+    }
+
+    protected abstract Subject<P, D, V> findInternal(Long key);
+
+    private Query findByAttrValueQuery(final String entityName) {
+        return entityManager.createQuery("SELECT e FROM " + entityName + " e"
+                + " WHERE e.attribute.schema.name = :schemaName AND (e.stringValue IS NOT NULL"
+                + " AND e.stringValue = :stringValue)"
+                + " OR (e.booleanValue IS NOT NULL AND e.booleanValue = :booleanValue)"
+                + " OR (e.dateValue IS NOT NULL AND e.dateValue = :dateValue)"
+                + " OR (e.longValue IS NOT NULL AND e.longValue = :longValue)"
+                + " OR (e.doubleValue IS NOT NULL AND e.doubleValue = :doubleValue)");
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public List<? extends Subject<P, D, V>> findByAttrValue(
+            final String schemaName, final PlainAttrValue attrValue, final AttributableUtil attrUtil) {
+
+        PlainSchema schema = plainSchemaDAO.find(schemaName, attrUtil.plainSchemaClass());
+        if (schema == null) {
+            LOG.error("Invalid schema name '{}'", schemaName);
+            return Collections.<Subject<P, D, V>>emptyList();
+        }
+
+        final String entityName = schema.isUniqueConstraint()
+                ? attrUtil.plainAttrUniqueValueClass().getName()
+                : attrUtil.plainAttrValueClass().getName();
+
+        Query query = findByAttrValueQuery(entityName);
+
+        query.setParameter("schemaName", schemaName);
+        query.setParameter("stringValue", attrValue.getStringValue());
+        query.setParameter("booleanValue", attrValue.getBooleanValue() == null
+                ? null
+                : ((AbstractPlainAttrValue) attrValue).getBooleanAsInteger(attrValue.getBooleanValue()));
+        if (attrValue.getDateValue() == null) {
+            query.setParameter("dateValue", null);
+        } else {
+            query.setParameter("dateValue", attrValue.getDateValue(), TemporalType.TIMESTAMP);
+        }
+        query.setParameter("longValue", attrValue.getLongValue());
+        query.setParameter("doubleValue", attrValue.getDoubleValue());
+
+        List<Subject<P, D, V>> result = new ArrayList<>();
+        for (PlainAttrValue value : (List<PlainAttrValue>) query.getResultList()) {
+            Subject<P, D, V> subject = (Subject<P, D, V>) value.getAttr().getOwner();
+            if (!result.contains(subject)) {
+                result.add(subject);
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public Subject<P, D, V> findByAttrUniqueValue(
+            final String schemaName, final PlainAttrValue attrUniqueValue, final AttributableUtil attrUtil) {
+
+        PlainSchema schema = plainSchemaDAO.find(schemaName, attrUtil.plainSchemaClass());
+        if (schema == null) {
+            LOG.error("Invalid schema name '{}'", schemaName);
+            return null;
+        }
+        if (!schema.isUniqueConstraint()) {
+            LOG.error("This schema has not unique constraint: '{}'", schemaName);
+            return null;
+        }
+
+        List<? extends Subject<P, D, V>> result = findByAttrValue(schemaName, attrUniqueValue, attrUtil);
+        return result.isEmpty()
+                ? null
+                : result.iterator().next();
+    }
+
+    /**
+     * Find users / roles by derived attribute value. This method could fail if one or more string literals contained
+     * into the derived attribute value provided derive from identifier (schema name) replacement. When you are going to
+     * specify a derived attribute expression you must be quite sure that string literals used to build the expression
+     * cannot be found into the attribute values used to replace attribute schema names used as identifiers.
+     *
+     * @param schemaName derived schema name
+     * @param value derived attribute value
+     * @param attrUtil AttributableUtil
+     * @return list of users / roles
+     */
+    @Override
+    public List<? extends Subject<P, D, V>> findByDerAttrValue(
+            final String schemaName, final String value, final AttributableUtil attrUtil) {
+
+        DerSchema schema = derSchemaDAO.find(schemaName, attrUtil.derSchemaClass());
+        if (schema == null) {
+            LOG.error("Invalid schema name '{}'", schemaName);
+            return Collections.<Subject<P, D, V>>emptyList();
+        }
+
+        // query string
+        final StringBuilder querystring = new StringBuilder();
+
+        boolean subquery = false;
+        for (String clause : getWhereClause(schema.getExpression(), value, attrUtil)) {
+            if (querystring.length() > 0) {
+                subquery = true;
+                querystring.append(" AND a.owner_id IN ( ");
+            }
+
+            querystring.append("SELECT a.owner_id ").
+                    append("FROM ").append(attrUtil.plainAttrClass().getSimpleName().substring(3)).append(" a, ").
+                    append(attrUtil.plainAttrValueClass().getSimpleName().substring(3)).append(" v, ").
+                    append(attrUtil.plainSchemaClass().getSimpleName().substring(3)).append(" s ").
+                    append("WHERE ").append(clause);
+
+            if (subquery) {
+                querystring.append(')');
+            }
+        }
+
+        LOG.debug("Execute query {}", querystring);
+
+        final Query query = entityManager.createNativeQuery(querystring.toString());
+
+        final List<Subject<P, D, V>> result = new ArrayList<>();
+        for (Object userId : query.getResultList()) {
+            Subject<P, D, V> subject = findInternal(Long.parseLong(userId.toString()));
+            if (!result.contains(subject)) {
+                result.add(subject);
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public List<? extends Subject<P, D, V>> findByResource(
+            final ExternalResource resource, final AttributableUtil attrUtil) {
+
+        Query query = entityManager.createQuery(
+                "SELECT e FROM " + attrUtil.attributableClass().getSimpleName() + " e "
+                + "WHERE :resource MEMBER OF e.resources");
+        query.setParameter("resource", resource);
+
+        return query.getResultList();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAAttrTemplateDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAAttrTemplateDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAAttrTemplateDAO.java
new file mode 100644
index 0000000..eb289b1
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAAttrTemplateDAO.java
@@ -0,0 +1,107 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.Collections;
+import java.util.List;
+import javax.persistence.Query;
+import org.apache.syncope.persistence.api.dao.AttrTemplateDAO;
+import org.apache.syncope.persistence.api.entity.AttrTemplate;
+import org.apache.syncope.persistence.api.entity.Schema;
+import org.apache.syncope.persistence.api.entity.membership.MDerAttrTemplate;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttrTemplate;
+import org.apache.syncope.persistence.api.entity.membership.MVirAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.RDerAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.RVirAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.AbstractAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMDerAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMPlainAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMVirAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.role.JPARDerAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.role.JPARPlainAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.role.JPARVirAttrTemplate;
+import org.springframework.stereotype.Repository;
+import org.springframework.util.ReflectionUtils;
+
+@Repository
+public class JPAAttrTemplateDAO<S extends Schema>
+        extends AbstractDAO<AttrTemplate<S>, Long> implements AttrTemplateDAO<S> {
+
+    private <T extends AttrTemplate<S>> Class<? extends AbstractAttrTemplate<? extends Schema>> getJPAEntityReference(
+            final Class<T> reference) {
+
+        return MPlainAttrTemplate.class.isAssignableFrom(reference)
+                ? JPAMPlainAttrTemplate.class
+                : MDerAttrTemplate.class.isAssignableFrom(reference)
+                        ? JPAMDerAttrTemplate.class
+                        : MVirAttrTemplate.class.isAssignableFrom(reference)
+                                ? JPAMVirAttrTemplate.class
+                                : RPlainAttrTemplate.class.isAssignableFrom(reference)
+                                        ? JPARPlainAttrTemplate.class
+                                        : RDerAttrTemplate.class.isAssignableFrom(reference)
+                                                ? JPARDerAttrTemplate.class
+                                                : RVirAttrTemplate.class.isAssignableFrom(reference)
+                                                        ? JPARVirAttrTemplate.class
+                                                        : null;
+    }
+
+    @Override
+    public <T extends AttrTemplate<S>> T find(final Long key, final Class<T> reference) {
+        return reference.cast(entityManager.find(getJPAEntityReference(reference), key));
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T extends AttrTemplate<S>> List<Number> findBySchemaName(
+            final String schemaName, final Class<T> reference) {
+
+        Query query = null;
+        try {
+            query = entityManager.createNativeQuery("SELECT id FROM "
+                    + ReflectionUtils.findField(getJPAEntityReference(reference), "TABLE").get(null).toString()
+                    + " WHERE schema_name=?1");
+            query.setParameter(1, schemaName);
+        } catch (Exception e) {
+            LOG.error("Unexpected exception", e);
+        }
+
+        return query == null ? Collections.<Number>emptyList() : query.getResultList();
+    }
+
+    @Override
+    public <T extends AttrTemplate<S>> void delete(final Long key, final Class<T> reference) {
+        T attrTemplate = find(key, reference);
+        if (attrTemplate == null) {
+            return;
+        }
+
+        delete(attrTemplate);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T extends AttrTemplate<S>> void delete(final T attrTemplate) {
+        if (attrTemplate.getOwner() != null) {
+            attrTemplate.getOwner().getAttrTemplates(attrTemplate.getClass()).remove(attrTemplate);
+        }
+
+        entityManager.remove(attrTemplate);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAConfDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAConfDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAConfDAO.java
new file mode 100644
index 0000000..d38b1cd
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAConfDAO.java
@@ -0,0 +1,106 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.persistence.api.dao.ConfDAO;
+import org.apache.syncope.persistence.api.dao.PlainAttrDAO;
+import org.apache.syncope.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.persistence.api.entity.conf.CPlainAttr;
+import org.apache.syncope.persistence.api.entity.conf.CPlainSchema;
+import org.apache.syncope.persistence.api.entity.conf.Conf;
+import org.apache.syncope.persistence.jpa.entity.JPAAttributableUtil;
+import org.apache.syncope.persistence.jpa.entity.conf.JPACPlainAttr;
+import org.apache.syncope.persistence.jpa.entity.conf.JPAConf;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+@Repository
+public class JPAConfDAO extends AbstractDAO<Conf, Long> implements ConfDAO {
+
+    @Autowired
+    private PlainSchemaDAO schemaDAO;
+
+    @Autowired
+    private PlainAttrDAO attrDAO;
+
+    @Override
+    public Conf get() {
+        Conf instance = entityManager.find(JPAConf.class, 1L);
+        if (instance == null) {
+            instance = new JPAConf();
+            instance.setKey(1L);
+
+            instance = entityManager.merge(instance);
+        }
+
+        return instance;
+    }
+
+    @Transactional(readOnly = true)
+    @Override
+    public CPlainAttr find(final String key) {
+        return get().getPlainAttr(key);
+    }
+
+    @Transactional(readOnly = true)
+    @Override
+    public CPlainAttr find(final String key, final String defaultValue) {
+        CPlainAttr result = find(key);
+        if (result == null) {
+            result = new JPACPlainAttr();
+            result.setSchema(schemaDAO.find(key, CPlainSchema.class));
+
+            result.addValue(defaultValue, JPAAttributableUtil.getInstance(AttributableType.CONFIGURATION));
+        }
+
+        return result;
+    }
+
+    @Override
+    public Conf save(final CPlainAttr attr) {
+        Conf instance = get();
+
+        CPlainAttr old = instance.getPlainAttr(attr.getSchema().getKey());
+        if (old != null && (!attr.getSchema().isUniqueConstraint()
+                || (!attr.getUniqueValue().getStringValue().equals(old.getUniqueValue().getStringValue())))) {
+
+            instance.removePlainAttr(old);
+            attrDAO.delete(old.getKey(), CPlainAttr.class);
+        }
+
+        instance.addPlainAttr(attr);
+        attr.setOwner(instance);
+
+        return entityManager.merge(instance);
+    }
+
+    @Override
+    public Conf delete(final String key) {
+        Conf instance = get();
+        CPlainAttr attr = instance.getPlainAttr(key);
+        if (attr != null) {
+            instance.removePlainAttr(attr);
+            instance = entityManager.merge(instance);
+        }
+
+        return instance;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAConnInstanceDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAConnInstanceDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAConnInstanceDAO.java
new file mode 100644
index 0000000..e1c5477
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAConnInstanceDAO.java
@@ -0,0 +1,90 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.persistence.api.dao.ConnInstanceDAO;
+import org.apache.syncope.persistence.api.dao.ExternalResourceDAO;
+import org.apache.syncope.persistence.api.dao.NotFoundException;
+import org.apache.syncope.persistence.api.entity.ConnInstance;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.jpa.entity.JPAConnInstance;
+import org.apache.syncope.provisioning.api.ConnectorRegistry;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class JPAConnInstanceDAO extends AbstractDAO<ConnInstance, Long> implements ConnInstanceDAO {
+
+    @Autowired
+    private ExternalResourceDAO resourceDAO;
+
+    @Autowired
+    private ConnectorRegistry connRegistry;
+
+    @Override
+    public ConnInstance find(final Long key) {
+        return entityManager.find(JPAConnInstance.class, key);
+    }
+
+    @Override
+    public List<ConnInstance> findAll() {
+        TypedQuery<ConnInstance> query = entityManager.createQuery(
+                "SELECT e FROM " + JPAConnInstance.class.getSimpleName() + " e", ConnInstance.class);
+        return query.getResultList();
+    }
+
+    @Override
+    public ConnInstance save(final ConnInstance connector) {
+        final ConnInstance merged = entityManager.merge(connector);
+
+        for (ExternalResource resource : merged.getResources()) {
+            try {
+                connRegistry.registerConnector(resource);
+            } catch (NotFoundException e) {
+                LOG.error("While registering connector for resource", e);
+            }
+        }
+
+        return merged;
+    }
+
+    @Override
+    public void delete(final Long key) {
+        ConnInstance connInstance = find(key);
+        if (connInstance == null) {
+            return;
+        }
+
+        Set<String> resourceNames = new HashSet<>(connInstance.getResources().size());
+        for (ExternalResource resource : connInstance.getResources()) {
+            resourceNames.add(resource.getKey());
+        }
+        for (String resourceName : resourceNames) {
+            resourceDAO.delete(resourceName);
+        }
+
+        entityManager.remove(connInstance);
+
+        connRegistry.unregisterConnector(key.toString());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPADerAttrDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPADerAttrDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPADerAttrDAO.java
new file mode 100644
index 0000000..ee452f8
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPADerAttrDAO.java
@@ -0,0 +1,86 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.List;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.persistence.api.dao.DerAttrDAO;
+import org.apache.syncope.persistence.api.entity.DerAttr;
+import org.apache.syncope.persistence.api.entity.Subject;
+import org.apache.syncope.persistence.api.entity.membership.MDerAttr;
+import org.apache.syncope.persistence.api.entity.role.RDerAttr;
+import org.apache.syncope.persistence.api.entity.user.UDerAttr;
+import org.apache.syncope.persistence.jpa.entity.AbstractDerAttr;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMDerAttr;
+import org.apache.syncope.persistence.jpa.entity.role.JPARDerAttr;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUDerAttr;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class JPADerAttrDAO extends AbstractDAO<DerAttr, Long> implements DerAttrDAO {
+
+    public <T extends DerAttr> Class<? extends AbstractDerAttr> getJPAEntityReference(
+            final Class<T> reference) {
+
+        return RDerAttr.class.isAssignableFrom(reference)
+                ? JPARDerAttr.class
+                : MDerAttr.class.isAssignableFrom(reference)
+                        ? JPAMDerAttr.class
+                        : UDerAttr.class.isAssignableFrom(reference)
+                                ? JPAUDerAttr.class
+                                : null;
+    }
+
+    @Override
+    public <T extends DerAttr> T find(final Long key, final Class<T> reference) {
+        return reference.cast(entityManager.find(getJPAEntityReference(reference), key));
+    }
+
+    @Override
+    public <T extends DerAttr> List<T> findAll(final Class<T> reference) {
+        TypedQuery<T> query = entityManager.createQuery(
+                "SELECT e FROM " + getJPAEntityReference(reference).getSimpleName() + " e", reference);
+        return query.getResultList();
+    }
+
+    @Override
+    public <T extends DerAttr> T save(final T derAttr) {
+        return entityManager.merge(derAttr);
+    }
+
+    @Override
+    public <T extends DerAttr> void delete(final Long key, final Class<T> reference) {
+        T derAttr = find(key, reference);
+        if (derAttr == null) {
+            return;
+        }
+
+        delete(derAttr);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T extends DerAttr> void delete(final T derAttr) {
+        if (derAttr.getOwner() != null) {
+            ((Subject<?, T, ?>) derAttr.getOwner()).removeDerAttr(derAttr);
+        }
+
+        entityManager.remove(derAttr);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPADerSchemaDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPADerSchemaDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPADerSchemaDAO.java
new file mode 100644
index 0000000..9a239fb
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPADerSchemaDAO.java
@@ -0,0 +1,132 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.persistence.api.dao.AttrTemplateDAO;
+import org.apache.syncope.persistence.api.dao.DerAttrDAO;
+import org.apache.syncope.persistence.api.dao.DerSchemaDAO;
+import org.apache.syncope.persistence.api.dao.ExternalResourceDAO;
+import org.apache.syncope.persistence.api.entity.AttributableUtil;
+import org.apache.syncope.persistence.api.entity.DerAttr;
+import org.apache.syncope.persistence.api.entity.DerSchema;
+import org.apache.syncope.persistence.api.entity.membership.MDerSchema;
+import org.apache.syncope.persistence.api.entity.role.RDerSchema;
+import org.apache.syncope.persistence.api.entity.user.UDerAttr;
+import org.apache.syncope.persistence.api.entity.user.UDerSchema;
+import org.apache.syncope.persistence.api.entity.user.UMappingItem;
+import org.apache.syncope.persistence.jpa.entity.AbstractDerSchema;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMDerSchema;
+import org.apache.syncope.persistence.jpa.entity.role.JPARDerSchema;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUDerSchema;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class JPADerSchemaDAO extends AbstractDAO<DerSchema, String> implements DerSchemaDAO {
+
+    @Autowired
+    private DerAttrDAO derAttrDAO;
+
+    @Autowired
+    private AttrTemplateDAO<DerSchema> attrTemplateDAO;
+
+    @Autowired
+    private ExternalResourceDAO resourceDAO;
+
+    private <T extends DerSchema> Class<? extends AbstractDerSchema> getJPAEntityReference(final Class<T> reference) {
+        return RDerSchema.class.isAssignableFrom(reference)
+                ? JPARDerSchema.class
+                : MDerSchema.class.isAssignableFrom(reference)
+                        ? JPAMDerSchema.class
+                        : UDerSchema.class.isAssignableFrom(reference)
+                                ? JPAUDerSchema.class
+                                : null;
+    }
+
+    @Override
+    public <T extends DerSchema> T find(final String key, final Class<T> reference) {
+        return reference.cast(entityManager.find(getJPAEntityReference(reference), key));
+    }
+
+    @Override
+    public <T extends DerSchema> List<T> findAll(final Class<T> reference) {
+        TypedQuery<T> query = entityManager.createQuery(
+                "SELECT e FROM " + getJPAEntityReference(reference).getSimpleName() + " e", reference);
+        return query.getResultList();
+    }
+
+    @Override
+    public <T extends DerAttr> List<T> findAttrs(final DerSchema schema, final Class<T> reference) {
+        final StringBuilder queryString = new StringBuilder("SELECT e FROM ").
+                append(((JPADerAttrDAO) derAttrDAO).getJPAEntityReference(reference).getSimpleName()).
+                append(" e WHERE e.");
+        if (UDerAttr.class.isAssignableFrom(reference)) {
+            queryString.append("derSchema");
+        } else {
+            queryString.append("template.schema");
+        }
+        queryString.append("=:schema");
+
+        TypedQuery<T> query = entityManager.createQuery(queryString.toString(), reference);
+        query.setParameter("schema", schema);
+
+        return query.getResultList();
+    }
+
+    @Override
+    public <T extends DerSchema> T save(final T derSchema) {
+        return entityManager.merge(derSchema);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public void delete(final String key, final AttributableUtil attributableUtil) {
+        final DerSchema schema = find(key, attributableUtil.derSchemaClass());
+        if (schema == null) {
+            return;
+        }
+
+        final Set<Long> attrIds = new HashSet<>();
+        for (DerAttr attr : findAttrs(schema, attributableUtil.derAttrClass())) {
+            attrIds.add(attr.getKey());
+        }
+        for (Long attrId : attrIds) {
+            derAttrDAO.delete(attrId, attributableUtil.derAttrClass());
+        }
+
+        if (attributableUtil.getType() != AttributableType.USER) {
+            for (Iterator<Number> it = attrTemplateDAO.
+                    findBySchemaName(schema.getKey(), attributableUtil.derAttrTemplateClass()).iterator();
+                    it.hasNext();) {
+
+                attrTemplateDAO.delete(it.next().longValue(), attributableUtil.derAttrTemplateClass());
+            }
+        }
+
+        resourceDAO.deleteMapping(key, attributableUtil.derIntMappingType(), UMappingItem.class);
+
+        entityManager.remove(schema);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAEntitlementDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAEntitlementDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAEntitlementDAO.java
new file mode 100644
index 0000000..cb7b90e
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAEntitlementDAO.java
@@ -0,0 +1,88 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.List;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.persistence.api.RoleEntitlementUtil;
+import org.apache.syncope.persistence.api.dao.EntitlementDAO;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.entity.Entitlement;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.jpa.entity.JPAEntitlement;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class JPAEntitlementDAO extends AbstractDAO<Entitlement, String> implements EntitlementDAO {
+
+    @Autowired
+    private RoleDAO roleDAO;
+
+    @Override
+    public Entitlement find(final String name) {
+        return entityManager.find(JPAEntitlement.class, name);
+    }
+
+    @Override
+    public List<Entitlement> findAll() {
+        TypedQuery<Entitlement> query = entityManager.createQuery(
+                "SELECT e FROM " + JPAEntitlement.class.getSimpleName() + " e", Entitlement.class);
+
+        return query.getResultList();
+    }
+
+    @Override
+    public Entitlement save(final Entitlement entitlement) {
+        return entityManager.merge(entitlement);
+    }
+
+    @Override
+    public Entitlement saveRoleEntitlement(final Role role) {
+        Entitlement roleEnt = new JPAEntitlement();
+        roleEnt.setKey(RoleEntitlementUtil.getEntitlementNameFromRoleId(role.getKey()));
+        roleEnt.setDescription("Entitlement for managing role " + role.getKey());
+
+        return save(roleEnt);
+    }
+
+    @Override
+    public void delete(final String name) {
+        Entitlement entitlement = find(name);
+        if (entitlement == null) {
+            return;
+        }
+
+        delete(entitlement);
+    }
+
+    @Override
+    public void delete(final Entitlement entitlement) {
+        if (entitlement == null) {
+            return;
+        }
+
+        for (Role role : roleDAO.findByEntitlement(entitlement)) {
+            role.removeEntitlement(entitlement);
+            roleDAO.save(role);
+        }
+
+        entityManager.remove(entitlement);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAExternalResourceDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAExternalResourceDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAExternalResourceDAO.java
new file mode 100644
index 0000000..c689ae8
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAExternalResourceDAO.java
@@ -0,0 +1,254 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.persistence.api.dao.ExternalResourceDAO;
+import org.apache.syncope.persistence.api.dao.NotFoundException;
+import org.apache.syncope.persistence.api.dao.PolicyDAO;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.dao.TaskDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.entity.AccountPolicy;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.Mapping;
+import org.apache.syncope.persistence.api.entity.MappingItem;
+import org.apache.syncope.persistence.api.entity.Policy;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.api.entity.task.PropagationTask;
+import org.apache.syncope.persistence.api.entity.task.PushTask;
+import org.apache.syncope.persistence.api.entity.task.SyncTask;
+import org.apache.syncope.persistence.api.entity.user.UMappingItem;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.entity.AbstractMappingItem;
+import org.apache.syncope.persistence.jpa.entity.JPAExternalResource;
+import org.apache.syncope.persistence.jpa.entity.role.JPARMappingItem;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUMappingItem;
+import org.apache.syncope.provisioning.api.ConnectorRegistry;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+@Repository
+public class JPAExternalResourceDAO extends AbstractDAO<ExternalResource, String> implements ExternalResourceDAO {
+
+    @Autowired
+    private TaskDAO taskDAO;
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Autowired
+    private RoleDAO roleDAO;
+
+    @Autowired
+    private PolicyDAO policyDAO;
+
+    @Autowired
+    private ConnectorRegistry connRegistry;
+
+    @Override
+    public ExternalResource find(final String name) {
+        TypedQuery<ExternalResource> query = entityManager.createQuery("SELECT e FROM "
+                + JPAExternalResource.class.getSimpleName() + " e WHERE e.name = :name", ExternalResource.class);
+        query.setParameter("name", name);
+
+        ExternalResource result = null;
+        try {
+            result = query.getSingleResult();
+        } catch (NoResultException e) {
+            LOG.debug("No resource found with name {}", name, e);
+        }
+
+        return result;
+    }
+
+    private StringBuilder getByPolicyQuery(final PolicyType type) {
+        StringBuilder query = new StringBuilder("SELECT e FROM ").
+                append(JPAExternalResource.class.getSimpleName()).
+                append(" e WHERE e.");
+        switch (type) {
+            case ACCOUNT:
+            case GLOBAL_ACCOUNT:
+                query.append("accountPolicy");
+                break;
+
+            case PASSWORD:
+            case GLOBAL_PASSWORD:
+                query.append("passwordPolicy");
+                break;
+
+            case SYNC:
+            case GLOBAL_SYNC:
+                query.append("syncPolicy");
+                break;
+
+            default:
+                break;
+        }
+        return query;
+    }
+
+    @Override
+    public List<ExternalResource> findByPolicy(final Policy policy) {
+        TypedQuery<ExternalResource> query = entityManager.createQuery(
+                getByPolicyQuery(policy.getType()).append(" = :policy").toString(), ExternalResource.class);
+        query.setParameter("policy", policy);
+        return query.getResultList();
+    }
+
+    @Override
+    public List<ExternalResource> findWithoutPolicy(final PolicyType type) {
+        TypedQuery<ExternalResource> query = entityManager.createQuery(
+                getByPolicyQuery(type).append(" IS NULL").toString(), ExternalResource.class);
+        return query.getResultList();
+    }
+
+    @Override
+    public List<ExternalResource> findAll() {
+        TypedQuery<ExternalResource> query = entityManager.createQuery(
+                "SELECT e FROM  " + JPAExternalResource.class.getSimpleName() + " e", ExternalResource.class);
+        return query.getResultList();
+    }
+
+    @Override
+    public List<ExternalResource> findAllByPriority() {
+        TypedQuery<ExternalResource> query = entityManager.createQuery(
+                "SELECT e FROM  " + JPAExternalResource.class.getSimpleName() + " e ORDER BY e.propagationPriority",
+                ExternalResource.class);
+        return query.getResultList();
+    }
+
+    /**
+     * This method has an explicit Transactional annotation because it is called by SyncJob.
+     *
+     * @see org.apache.syncope.core.sync.impl.SyncJob
+     *
+     * @param resource entity to be merged
+     * @return the same entity, updated
+     */
+    @Override
+    @Transactional(rollbackFor = { Throwable.class })
+    public ExternalResource save(final ExternalResource resource) {
+        ExternalResource merged = entityManager.merge(resource);
+        try {
+            connRegistry.registerConnector(merged);
+        } catch (NotFoundException e) {
+            LOG.error("While registering connector for resource", e);
+        }
+        return merged;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T extends MappingItem> void deleteMapping(
+            final String intAttrName, final IntMappingType intMappingType, final Class<T> reference) {
+
+        if (IntMappingType.getEmbedded().contains(intMappingType)) {
+            return;
+        }
+
+        Class<? extends AbstractMappingItem> jpaRef = reference.equals(UMappingItem.class)
+                ? JPAUMappingItem.class
+                : JPARMappingItem.class;
+
+        TypedQuery<T> query = entityManager.createQuery("SELECT m FROM " + jpaRef.getSimpleName()
+                + " m WHERE m.intAttrName=:intAttrName AND m.intMappingType=:intMappingType", reference);
+        query.setParameter("intAttrName", intAttrName);
+        query.setParameter("intMappingType", intMappingType);
+
+        Set<Long> itemIds = new HashSet<>();
+        for (T item : query.getResultList()) {
+            itemIds.add(item.getKey());
+        }
+        Class<?> mappingRef = null;
+        for (Long itemId : itemIds) {
+            T item = (T) entityManager.find(jpaRef, itemId);
+            if (item != null) {
+                mappingRef = item.getMapping().getClass();
+
+                ((Mapping<T>) item.getMapping()).removeItem(item);
+                item.setMapping(null);
+
+                entityManager.remove(item);
+            }
+        }
+
+        // Make empty query cache for *MappingItem and related *Mapping
+        entityManager.getEntityManagerFactory().getCache().evict(jpaRef);
+        if (mappingRef != null) {
+            entityManager.getEntityManagerFactory().getCache().evict(mappingRef);
+        }
+    }
+
+    @Override
+    public void delete(final String name) {
+        ExternalResource resource = find(name);
+        if (resource == null) {
+            return;
+        }
+
+        taskDAO.deleteAll(resource, TaskType.PROPAGATION);
+        taskDAO.deleteAll(resource, TaskType.SYNCHRONIZATION);
+        taskDAO.deleteAll(resource, TaskType.PUSH);
+
+        for (User user : userDAO.findByResource(resource)) {
+            user.removeResource(resource);
+        }
+        for (Role role : roleDAO.findByResource(resource)) {
+            role.removeResource(resource);
+        }
+        for (AccountPolicy policy : policyDAO.findByResource(resource)) {
+            policy.removeResource(resource);
+        }
+
+        if (resource.getConnector() != null && resource.getConnector().getResources() != null
+                && !resource.getConnector().getResources().isEmpty()) {
+
+            resource.getConnector().getResources().remove(resource);
+        }
+        resource.setConnector(null);
+
+        if (resource.getUmapping() != null) {
+            for (MappingItem item : resource.getUmapping().getItems()) {
+                item.setMapping(null);
+            }
+            resource.getUmapping().getItems().clear();
+            resource.getUmapping().setResource(null);
+            resource.setUmapping(null);
+        }
+        if (resource.getRmapping() != null) {
+            for (MappingItem item : resource.getRmapping().getItems()) {
+                item.setMapping(null);
+            }
+            resource.getRmapping().getItems().clear();
+            resource.getRmapping().setResource(null);
+            resource.setRmapping(null);
+        }
+
+        entityManager.remove(resource);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPALoggerDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPALoggerDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPALoggerDAO.java
new file mode 100644
index 0000000..b615fdc
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPALoggerDAO.java
@@ -0,0 +1,69 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.List;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.common.lib.types.LoggerLevel;
+import org.apache.syncope.common.lib.types.LoggerType;
+import org.apache.syncope.persistence.api.dao.LoggerDAO;
+import org.apache.syncope.persistence.api.entity.Logger;
+import org.apache.syncope.persistence.jpa.entity.JPALogger;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class JPALoggerDAO extends AbstractDAO<Logger, String> implements LoggerDAO {
+
+    @Override
+    public Logger find(final String key) {
+        return entityManager.find(JPALogger.class, key);
+    }
+
+    @Override
+    public List<Logger> findAll(final LoggerType type) {
+        TypedQuery<Logger> query = entityManager.createQuery(
+                "SELECT e FROM " + JPALogger.class.getSimpleName() + " e WHERE e.type=:type", Logger.class);
+        query.setParameter("type", type);
+        return query.getResultList();
+    }
+
+    @Override
+    public Logger save(final Logger logger) {
+        // Audit loggers must be either OFF or DEBUG, no more options
+        if (LoggerType.AUDIT == logger.getType() && LoggerLevel.OFF != logger.getLevel()) {
+            logger.setLevel(LoggerLevel.DEBUG);
+        }
+        return entityManager.merge(logger);
+    }
+
+    @Override
+    public void delete(final Logger logger) {
+        entityManager.remove(logger);
+    }
+
+    @Override
+    public void delete(final String key) {
+        Logger logger = find(key);
+        if (logger == null) {
+            return;
+        }
+
+        delete(logger);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAMembershipDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAMembershipDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAMembershipDAO.java
new file mode 100644
index 0000000..af6dbd2
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAMembershipDAO.java
@@ -0,0 +1,87 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.List;
+import javax.persistence.NoResultException;
+import javax.persistence.Query;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.persistence.api.dao.MembershipDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.entity.membership.Membership;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMembership;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class JPAMembershipDAO extends AbstractDAO<Membership, Long> implements MembershipDAO {
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Override
+    public Membership find(final Long key) {
+        return entityManager.find(JPAMembership.class, key);
+    }
+
+    @Override
+    public Membership find(final User user, final Role role) {
+        Query query = entityManager.createQuery(
+                "SELECT e FROM " + JPAMembership.class.getSimpleName() + " e WHERE e.user = :user AND e.role = :role");
+        query.setParameter("user", user);
+        query.setParameter("role", role);
+
+        Membership result = null;
+
+        try {
+            result = (Membership) query.getSingleResult();
+        } catch (NoResultException e) {
+            LOG.debug("No membership was found for user {} and role {}", user, role, e);
+        }
+
+        return result;
+    }
+
+    @Override
+    public List<Membership> findAll() {
+        TypedQuery<Membership> query = entityManager.createQuery(
+                "SELECT e FROM " + JPAMembership.class.getSimpleName() + " e", Membership.class);
+        return query.getResultList();
+    }
+
+    @Override
+    public Membership save(final Membership membership) {
+        return entityManager.merge(membership);
+    }
+
+    @Override
+    public void delete(final Long key) {
+        Membership membership = find(key);
+        if (membership == null) {
+            return;
+        }
+
+        membership.getUser().removeMembership(membership);
+        userDAO.save(membership.getUser());
+
+        entityManager.remove(membership);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPANotificationDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPANotificationDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPANotificationDAO.java
new file mode 100644
index 0000000..b9cab70
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPANotificationDAO.java
@@ -0,0 +1,53 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import java.util.List;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.persistence.api.dao.NotificationDAO;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.entity.Notification;
+import org.apache.syncope.persistence.jpa.entity.JPANotification;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class JPANotificationDAO extends AbstractDAO<Notification, Long> implements NotificationDAO {
+
+    @Override
+    public Notification find(final Long key) {
+        return entityManager.find(JPANotification.class, key);
+    }
+
+    @Override
+    public List<Notification> findAll() {
+        TypedQuery<Notification> query = entityManager.createQuery(
+                "SELECT e FROM " + JPANotification.class.getSimpleName() + " e", Notification.class);
+        return query.getResultList();
+    }
+
+    @Override
+    public Notification save(final Notification notification) throws InvalidEntityException {
+        return entityManager.merge(notification);
+    }
+
+    @Override
+    public void delete(final Long key) {
+        entityManager.remove(find(key));
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAPlainAttrDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAPlainAttrDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAPlainAttrDAO.java
new file mode 100644
index 0000000..52a260d
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/JPAPlainAttrDAO.java
@@ -0,0 +1,76 @@
+/*
+ * 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.persistence.jpa.dao;
+
+import org.apache.syncope.persistence.api.dao.PlainAttrDAO;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.Subject;
+import org.apache.syncope.persistence.api.entity.conf.CPlainAttr;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttr;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttr;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttr;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainAttr;
+import org.apache.syncope.persistence.jpa.entity.conf.JPACPlainAttr;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMPlainAttr;
+import org.apache.syncope.persistence.jpa.entity.role.JPARPlainAttr;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUPlainAttr;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class JPAPlainAttrDAO extends AbstractDAO<PlainAttr, Long> implements PlainAttrDAO {
+
+    public <T extends PlainAttr> Class<? extends AbstractPlainAttr> getJPAEntityReference(
+            final Class<T> reference) {
+
+        return CPlainAttr.class.isAssignableFrom(reference)
+                ? JPACPlainAttr.class
+                : RPlainAttr.class.isAssignableFrom(reference)
+                        ? JPARPlainAttr.class
+                        : MPlainAttr.class.isAssignableFrom(reference)
+                                ? JPAMPlainAttr.class
+                                : UPlainAttr.class.isAssignableFrom(reference)
+                                        ? JPAUPlainAttr.class
+                                        : null;
+    }
+
+    @Override
+    public <T extends PlainAttr> T find(final Long key, final Class<T> reference) {
+        return reference.cast(entityManager.find(getJPAEntityReference(reference), key));
+    }
+
+    @Override
+    public <T extends PlainAttr> void delete(final Long key, final Class<T> reference) {
+        T attribute = find(key, reference);
+        if (attribute == null) {
+            return;
+        }
+
+        delete(attribute);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T extends PlainAttr> void delete(final T plainAttr) {
+        if (plainAttr.getOwner() != null) {
+            ((Subject<T, ?, ?>) plainAttr.getOwner()).removePlainAttr(plainAttr);
+        }
+
+        entityManager.remove(plainAttr);
+    }
+}


[23/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARDerSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARDerSchema.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARDerSchema.java
new file mode 100644
index 0000000..19ec371
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARDerSchema.java
@@ -0,0 +1,34 @@
+/*
+ * 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.persistence.jpa.entity.role;
+
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.role.RDerSchema;
+import org.apache.syncope.persistence.jpa.entity.AbstractDerSchema;
+
+@Entity
+@Table(name = JPARDerSchema.TABLE)
+public class JPARDerSchema extends AbstractDerSchema implements RDerSchema {
+
+    private static final long serialVersionUID = -6868889736207576372L;
+
+    public static final String TABLE = "RDerSchema";
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARMapping.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARMapping.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARMapping.java
new file mode 100644
index 0000000..00af59a
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARMapping.java
@@ -0,0 +1,103 @@
+/*
+ * 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.persistence.jpa.entity.role;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.role.RMapping;
+import org.apache.syncope.persistence.api.entity.role.RMappingItem;
+import org.apache.syncope.persistence.jpa.entity.AbstractMapping;
+import org.apache.syncope.persistence.jpa.entity.JPAExternalResource;
+
+@Entity
+@Table(name = JPARMapping.TABLE)
+public class JPARMapping extends AbstractMapping<RMappingItem> implements RMapping {
+
+    public static final String TABLE = "RMapping";
+
+    private static final long serialVersionUID = 4578756002867863392L;
+
+    @Id
+    private Long id;
+
+    /**
+     * Resource owning this mapping.
+     */
+    @OneToOne
+    private JPAExternalResource resource;
+
+    /**
+     * Attribute mappings.
+     */
+    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "mapping")
+    private List<JPARMappingItem> items;
+
+    public JPARMapping() {
+        super();
+
+        items = new ArrayList<>();
+    }
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public ExternalResource getResource() {
+        return resource;
+    }
+
+    @Override
+    public void setResource(final ExternalResource resource) {
+        checkType(resource, JPAExternalResource.class);
+        this.resource = (JPAExternalResource) resource;
+    }
+
+    @Override
+    public void setAccountIdItem(final RMappingItem item) {
+        checkType(item, JPARMappingItem.class);
+        this.addAccountIdItem((JPARMappingItem) item);
+    }
+
+    @Override
+    public List<? extends RMappingItem> getItems() {
+        return items;
+    }
+
+    @Override
+    public boolean addItem(final RMappingItem item) {
+        checkType(item, JPARMappingItem.class);
+        return items.contains((JPARMappingItem) item) || items.add((JPARMappingItem) item);
+    }
+
+    @Override
+    public boolean removeItem(final RMappingItem item) {
+        checkType(item, JPARMappingItem.class);
+        return items.remove((JPARMappingItem) item);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARMappingItem.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARMappingItem.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARMappingItem.java
new file mode 100644
index 0000000..68fb3bd
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARMappingItem.java
@@ -0,0 +1,58 @@
+/*
+ * 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.persistence.jpa.entity.role;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.Mapping;
+import org.apache.syncope.persistence.api.entity.role.RMappingItem;
+import org.apache.syncope.persistence.jpa.entity.AbstractMappingItem;
+
+@Entity
+@Table(name = JPARMappingItem.TABLE)
+public class JPARMappingItem extends AbstractMappingItem implements RMappingItem {
+
+    public static final String TABLE = "RMappingItem";
+
+    private static final long serialVersionUID = -2670787666933476166L;
+
+    @Id
+    private Long id;
+
+    @ManyToOne
+    private JPARMapping mapping;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public Mapping<RMappingItem> getMapping() {
+        return mapping;
+    }
+
+    @Override
+    public void setMapping(final Mapping<?> mapping) {
+        checkType(mapping, JPARMapping.class);
+        this.mapping = (JPARMapping) mapping;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainAttr.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainAttr.java
new file mode 100644
index 0000000..243c0db
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainAttr.java
@@ -0,0 +1,140 @@
+/*
+ * 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.persistence.jpa.entity.role;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.validation.Valid;
+import org.apache.syncope.persistence.api.entity.Attributable;
+import org.apache.syncope.persistence.api.entity.PlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttr;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttrValue;
+import org.apache.syncope.persistence.api.entity.role.RPlainSchema;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainAttr;
+
+@Entity
+@Table(name = JPARPlainAttr.TABLE)
+public class JPARPlainAttr extends AbstractPlainAttr implements RPlainAttr {
+
+    private static final long serialVersionUID = 2848159565890995780L;
+
+    public static final String TABLE = "RPlainAttr";
+
+    @Id
+    private Long id;
+
+    @ManyToOne(fetch = FetchType.EAGER)
+    private JPARole owner;
+
+    @Column(nullable = false)
+    @OneToOne(cascade = CascadeType.MERGE)
+    private JPARPlainAttrTemplate template;
+
+    @OneToMany(cascade = CascadeType.MERGE, orphanRemoval = true, mappedBy = "attribute")
+    @Valid
+    private List<JPARPlainAttrValue> values;
+
+    @OneToOne(cascade = CascadeType.ALL, mappedBy = "attribute")
+    @Valid
+    private JPARPlainAttrUniqueValue uniqueValue;
+
+    public JPARPlainAttr() {
+        super();
+        values = new ArrayList<>();
+    }
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public Role getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final Attributable<?, ?, ?> owner) {
+        checkType(owner, JPARole.class);
+        this.owner = (JPARole) owner;
+    }
+
+    @Override
+    public RPlainAttrTemplate getTemplate() {
+        return template;
+    }
+
+    @Override
+    public void setTemplate(final RPlainAttrTemplate template) {
+        checkType(template, JPARPlainAttrTemplate.class);
+        this.template = (JPARPlainAttrTemplate) template;
+    }
+
+    @Override
+    public RPlainSchema getSchema() {
+        return template == null ? null : template.getSchema();
+    }
+
+    @Override
+    public void setSchema(final PlainSchema schema) {
+        LOG.warn("This is role attribute, set template to select schema");
+    }
+
+    @Override
+    protected boolean addValue(final PlainAttrValue attrValue) {
+        checkType(attrValue, JPARPlainAttrValue.class);
+        return values.add((JPARPlainAttrValue) attrValue);
+    }
+
+    @Override
+    public boolean removeValue(final PlainAttrValue attrValue) {
+        checkType(attrValue, JPARPlainAttrValue.class);
+        return values.remove((JPARPlainAttrValue) attrValue);
+    }
+
+    @Override
+    public List<? extends RPlainAttrValue> getValues() {
+        return values;
+    }
+
+    @Override
+    public RPlainAttrUniqueValue getUniqueValue() {
+        return uniqueValue;
+    }
+
+    @Override
+    public void setUniqueValue(final PlainAttrUniqueValue uniqueValue) {
+        checkType(owner, JPARPlainAttrUniqueValue.class);
+        this.uniqueValue = (JPARPlainAttrUniqueValue) uniqueValue;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainAttrTemplate.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainAttrTemplate.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainAttrTemplate.java
new file mode 100644
index 0000000..90ac153
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainAttrTemplate.java
@@ -0,0 +1,66 @@
+/*
+ * 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.persistence.jpa.entity.role;
+
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.RPlainSchema;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.jpa.entity.AbstractAttrTemplate;
+
+@Entity
+@Table(name = JPARPlainAttrTemplate.TABLE)
+public class JPARPlainAttrTemplate extends AbstractAttrTemplate<RPlainSchema> implements RPlainAttrTemplate {
+
+    private static final long serialVersionUID = -3424574558427502145L;
+
+    public static final String TABLE = "RPlainAttrTemplate";
+
+    @ManyToOne
+    private JPARole owner;
+
+    @ManyToOne
+    @JoinColumn(name = "schema_name")
+    private JPARPlainSchema schema;
+
+    @Override
+    public RPlainSchema getSchema() {
+        return schema;
+    }
+
+    @Override
+    public void setSchema(final RPlainSchema schema) {
+        checkType(schema, JPARPlainSchema.class);
+        this.schema = (JPARPlainSchema) schema;
+    }
+
+    @Override
+    public Role getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final Role owner) {
+        checkType(owner, JPARole.class);
+        this.owner = (JPARole) owner;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainAttrUniqueValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainAttrUniqueValue.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainAttrUniqueValue.java
new file mode 100644
index 0000000..7a4cdb9
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainAttrUniqueValue.java
@@ -0,0 +1,78 @@
+/*
+ * 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.persistence.jpa.entity.role;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttr;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.role.RPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainAttrValue;
+
+@Entity
+@Table(name = JPARPlainAttrUniqueValue.TABLE)
+public class JPARPlainAttrUniqueValue extends AbstractPlainAttrValue implements RPlainAttrUniqueValue {
+
+    private static final long serialVersionUID = 4681561795607192855L;
+
+    public static final String TABLE = "RPlainAttrUniqueValue";
+
+    @Id
+    private Long id;
+
+    @OneToOne(optional = false)
+    private JPARPlainAttr attribute;
+
+    @ManyToOne(optional = false)
+    @JoinColumn(name = "schema_name")
+    private JPARPlainSchema schema;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public RPlainAttr getAttr() {
+        return attribute;
+    }
+
+    @Override
+    public void setAttr(final PlainAttr attr) {
+        checkType(attr, JPARPlainAttr.class);
+        this.attribute = (JPARPlainAttr) attr;
+    }
+
+    @Override
+    public RPlainSchema getSchema() {
+        return schema;
+    }
+
+    @Override
+    public void setSchema(final PlainSchema schema) {
+        checkType(schema, JPARPlainSchema.class);
+        this.schema = (JPARPlainSchema) schema;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainAttrValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainAttrValue.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainAttrValue.java
new file mode 100644
index 0000000..428e641
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainAttrValue.java
@@ -0,0 +1,64 @@
+/*
+ * 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.persistence.jpa.entity.role;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttr;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttrValue;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainAttrValue;
+
+@Entity
+@Table(name = JPARPlainAttrValue.TABLE)
+@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
+public class JPARPlainAttrValue extends AbstractPlainAttrValue implements RPlainAttrValue {
+
+    private static final long serialVersionUID = -766808291128424707L;
+
+    public static final String TABLE = "RPlainAttrValue";
+
+    @Id
+    private Long id;
+
+    @ManyToOne
+    @NotNull
+    private JPARPlainAttr attribute;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public RPlainAttr getAttr() {
+        return attribute;
+    }
+
+    @Override
+    public void setAttr(final PlainAttr attr) {
+        checkType(attr, JPARPlainAttr.class);
+        this.attribute = (JPARPlainAttr) attr;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainSchema.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainSchema.java
new file mode 100644
index 0000000..5b1d019
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARPlainSchema.java
@@ -0,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.persistence.jpa.entity.role;
+
+import javax.persistence.Cacheable;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.role.RPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainSchema;
+
+@Entity
+@Table(name = JPARPlainSchema.TABLE)
+@Cacheable
+public class JPARPlainSchema extends AbstractPlainSchema implements RPlainSchema {
+
+    private static final long serialVersionUID = -7417234690221851342L;
+
+    public static final String TABLE = "RPlainSchema";
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARVirAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARVirAttr.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARVirAttr.java
new file mode 100644
index 0000000..6795a63
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARVirAttr.java
@@ -0,0 +1,82 @@
+/*
+ * 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.persistence.jpa.entity.role;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.Attributable;
+import org.apache.syncope.persistence.api.entity.VirSchema;
+import org.apache.syncope.persistence.api.entity.role.RVirAttr;
+import org.apache.syncope.persistence.api.entity.role.RVirAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.RVirSchema;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.jpa.entity.AbstractVirAttr;
+
+@Entity
+@Table(name = JPARVirAttr.TABLE)
+public class JPARVirAttr extends AbstractVirAttr implements RVirAttr {
+
+    private static final long serialVersionUID = -1747430556914428649L;
+
+    public static final String TABLE = "RVirAttr";
+
+    @ManyToOne
+    private JPARole owner;
+
+    @Column(nullable = false)
+    @OneToOne(cascade = CascadeType.MERGE)
+    private JPARVirAttrTemplate template;
+
+    @Override
+    public Role getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final Attributable<?, ?, ?> owner) {
+        checkType(owner, JPARole.class);
+        this.owner = (JPARole) owner;
+    }
+
+    @Override
+    public RVirAttrTemplate getTemplate() {
+        return template;
+    }
+
+    @Override
+    public void setTemplate(final RVirAttrTemplate template) {
+        checkType(template, JPARVirAttrTemplate.class);
+        this.template = (JPARVirAttrTemplate) template;
+    }
+
+    @Override
+    public RVirSchema getSchema() {
+        return template == null ? null : template.getSchema();
+    }
+
+    @Override
+    public void setSchema(final VirSchema schema) {
+        LOG.warn("This is role attribute, set template to select schema");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARVirAttrTemplate.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARVirAttrTemplate.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARVirAttrTemplate.java
new file mode 100644
index 0000000..a5e41bd
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARVirAttrTemplate.java
@@ -0,0 +1,66 @@
+/*
+ * 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.persistence.jpa.entity.role;
+
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.role.RVirAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.RVirSchema;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.jpa.entity.AbstractAttrTemplate;
+
+@Entity
+@Table(name = JPARVirAttrTemplate.TABLE)
+public class JPARVirAttrTemplate extends AbstractAttrTemplate<RVirSchema> implements RVirAttrTemplate {
+
+    private static final long serialVersionUID = -3424574558427502145L;
+
+    public static final String TABLE = "RVirAttrTemplate";
+
+    @ManyToOne
+    private JPARole owner;
+
+    @ManyToOne
+    @JoinColumn(name = "schema_name")
+    private JPARVirSchema schema;
+
+    @Override
+    public RVirSchema getSchema() {
+        return schema;
+    }
+
+    @Override
+    public void setSchema(final RVirSchema schema) {
+        checkType(schema, JPARVirSchema.class);
+        this.schema = (JPARVirSchema) schema;
+    }
+
+    @Override
+    public Role getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final Role role) {
+        checkType(role, JPARole.class);
+        this.owner = (JPARole) role;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARVirSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARVirSchema.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARVirSchema.java
new file mode 100644
index 0000000..0a4fa9d
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARVirSchema.java
@@ -0,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.persistence.jpa.entity.role;
+
+import javax.persistence.Cacheable;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.role.RVirSchema;
+import org.apache.syncope.persistence.jpa.entity.AbstractVirSchema;
+
+@Entity
+@Table(name = JPARVirSchema.TABLE)
+@Cacheable
+public class JPARVirSchema extends AbstractVirSchema implements RVirSchema {
+
+    private static final long serialVersionUID = -2595041749349652939L;
+
+    public static final String TABLE = "RVirSchema";
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARole.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARole.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARole.java
new file mode 100644
index 0000000..05c9e9f
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARole.java
@@ -0,0 +1,593 @@
+/*
+ * 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.persistence.jpa.entity.role;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.persistence.Basic;
+import javax.persistence.Cacheable;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+import javax.validation.Valid;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import org.apache.syncope.persistence.api.entity.AccountPolicy;
+import org.apache.syncope.persistence.api.entity.AttrTemplate;
+import org.apache.syncope.persistence.api.entity.DerSchema;
+import org.apache.syncope.persistence.api.entity.Entitlement;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.PasswordPolicy;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.apache.syncope.persistence.api.entity.Schema;
+import org.apache.syncope.persistence.api.entity.VirSchema;
+import org.apache.syncope.persistence.api.entity.membership.MDerAttrTemplate;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttrTemplate;
+import org.apache.syncope.persistence.api.entity.membership.MVirAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.RDerAttr;
+import org.apache.syncope.persistence.api.entity.role.RDerAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.RDerSchema;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttr;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.RVirAttr;
+import org.apache.syncope.persistence.api.entity.role.RVirAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.RVirSchema;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.validation.entity.RoleCheck;
+import org.apache.syncope.persistence.jpa.entity.AbstractSubject;
+import org.apache.syncope.persistence.jpa.entity.JPAAccountPolicy;
+import org.apache.syncope.persistence.jpa.entity.JPAEntitlement;
+import org.apache.syncope.persistence.jpa.entity.JPAExternalResource;
+import org.apache.syncope.persistence.jpa.entity.JPAPasswordPolicy;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMPlainAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMDerAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMVirAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUser;
+
+@Entity
+@Table(name = JPARole.TABLE, uniqueConstraints =
+        @UniqueConstraint(columnNames = { "name", "parent_id" }))
+@Cacheable
+@RoleCheck
+public class JPARole extends AbstractSubject<RPlainAttr, RDerAttr, RVirAttr> implements Role {
+
+    private static final long serialVersionUID = -5281258853142421875L;
+
+    public static final String TABLE = "SyncopeRole";
+
+    @Id
+    private Long id;
+
+    @NotNull
+    private String name;
+
+    @ManyToOne(optional = true)
+    private JPARole parent;
+
+    @ManyToOne(optional = true)
+    private JPAUser userOwner;
+
+    @ManyToOne(optional = true)
+    private JPARole roleOwner;
+
+    @ManyToMany(fetch = FetchType.EAGER)
+    @JoinTable(joinColumns =
+            @JoinColumn(name = "role_id"),
+            inverseJoinColumns =
+            @JoinColumn(name = "entitlement_name"))
+    private Set<JPAEntitlement> entitlements;
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPARPlainAttrTemplate> rAttrTemplates;
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPARDerAttrTemplate> rDerAttrTemplates;
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPARVirAttrTemplate> rVirAttrTemplates;
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPAMPlainAttrTemplate> mAttrTemplates;
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPAMDerAttrTemplate> mDerAttrTemplates;
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPAMVirAttrTemplate> mVirAttrTemplates;
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPARPlainAttr> plainAttrs;
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPARDerAttr> derAttrs;
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPARVirAttr> virAttrs;
+
+    @Basic(optional = true)
+    @Min(0)
+    @Max(1)
+    private Integer inheritOwner;
+
+    @Basic(optional = true)
+    @Min(0)
+    @Max(1)
+    private Integer inheritTemplates;
+
+    @Basic(optional = true)
+    @Min(0)
+    @Max(1)
+    private Integer inheritAttrs;
+
+    @Basic(optional = true)
+    @Min(0)
+    @Max(1)
+    private Integer inheritDerAttrs;
+
+    @Basic(optional = true)
+    @Min(0)
+    @Max(1)
+    private Integer inheritVirAttrs;
+
+    @Basic(optional = true)
+    @Min(0)
+    @Max(1)
+    private Integer inheritPasswordPolicy;
+
+    @Basic(optional = true)
+    @Min(0)
+    @Max(1)
+    private Integer inheritAccountPolicy;
+
+    @ManyToOne(fetch = FetchType.EAGER, optional = true)
+    private JPAPasswordPolicy passwordPolicy;
+
+    @ManyToOne(fetch = FetchType.EAGER, optional = true)
+    private JPAAccountPolicy accountPolicy;
+
+    /**
+     * Provisioning external resources.
+     */
+    @ManyToMany(fetch = FetchType.EAGER)
+    @JoinTable(joinColumns =
+            @JoinColumn(name = "role_id"),
+            inverseJoinColumns =
+            @JoinColumn(name = "resource_name"))
+    @Valid
+    private Set<JPAExternalResource> resources;
+
+    public JPARole() {
+        super();
+
+        entitlements = new HashSet<>();
+
+        rAttrTemplates = new ArrayList<>();
+        rDerAttrTemplates = new ArrayList<>();
+        rVirAttrTemplates = new ArrayList<>();
+        mAttrTemplates = new ArrayList<>();
+        mDerAttrTemplates = new ArrayList<>();
+        mVirAttrTemplates = new ArrayList<>();
+
+        plainAttrs = new ArrayList<>();
+        derAttrs = new ArrayList<>();
+        virAttrs = new ArrayList<>();
+
+        inheritOwner = getBooleanAsInteger(false);
+        inheritTemplates = getBooleanAsInteger(false);
+        inheritAttrs = getBooleanAsInteger(false);
+        inheritDerAttrs = getBooleanAsInteger(false);
+        inheritVirAttrs = getBooleanAsInteger(false);
+        inheritPasswordPolicy = getBooleanAsInteger(false);
+        inheritAccountPolicy = getBooleanAsInteger(false);
+
+        resources = new HashSet<>();
+    }
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    protected Set<? extends ExternalResource> internalGetResources() {
+        return resources;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    @Override
+    public Role getParent() {
+        return parent;
+    }
+
+    @Override
+    public void setParent(final Role parent) {
+        checkType(parent, JPARole.class);
+        this.parent = (JPARole) parent;
+    }
+
+    @Override
+    public boolean isInheritOwner() {
+        return isBooleanAsInteger(inheritOwner);
+    }
+
+    @Override
+    public void setInheritOwner(final boolean inheritOwner) {
+        this.inheritOwner = getBooleanAsInteger(inheritOwner);
+    }
+
+    @Override
+    public User getUserOwner() {
+        return userOwner;
+    }
+
+    @Override
+    public void setUserOwner(final User userOwner) {
+        checkType(userOwner, JPAUser.class);
+        this.userOwner = (JPAUser) userOwner;
+    }
+
+    @Override
+    public JPARole getRoleOwner() {
+        return roleOwner;
+    }
+
+    @Override
+    public void setRoleOwner(final Role roleOwner) {
+        checkType(roleOwner, JPARole.class);
+        this.roleOwner = (JPARole) roleOwner;
+    }
+
+    @Override
+    public boolean addEntitlement(final Entitlement entitlement) {
+        checkType(entitlement, JPAEntitlement.class);
+        return entitlements.add((JPAEntitlement) entitlement);
+    }
+
+    @Override
+    public boolean removeEntitlement(final Entitlement entitlement) {
+        checkType(entitlement, JPAEntitlement.class);
+        return entitlements.remove((JPAEntitlement) entitlement);
+    }
+
+    @Override
+    public Set<? extends Entitlement> getEntitlements() {
+        return entitlements;
+    }
+
+    @Override
+    public boolean isInheritTemplates() {
+        return isBooleanAsInteger(inheritTemplates);
+    }
+
+    @Override
+    public void setInheritTemplates(final boolean inheritAttrTemplates) {
+        this.inheritTemplates = getBooleanAsInteger(inheritAttrTemplates);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T extends AttrTemplate<K>, K extends Schema> List<T> getAttrTemplates(final Class<T> reference) {
+        List<T> result = new ArrayList<>();
+
+        if (RPlainAttrTemplate.class.isAssignableFrom(reference)) {
+            result = (List<T>) rAttrTemplates;
+        } else if (RDerAttrTemplate.class.isAssignableFrom(reference)) {
+            result = (List<T>) rDerAttrTemplates;
+        } else if (RVirAttrTemplate.class.isAssignableFrom(reference)) {
+            result = (List<T>) rVirAttrTemplates;
+        } else if (MPlainAttrTemplate.class.isAssignableFrom(reference)) {
+            result = (List<T>) mAttrTemplates;
+        } else if (MDerAttrTemplate.class.isAssignableFrom(reference)) {
+            result = (List<T>) mDerAttrTemplates;
+        } else if (MVirAttrTemplate.class.isAssignableFrom(reference)) {
+            result = (List<T>) mVirAttrTemplates;
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends AttrTemplate<K>, K extends Schema> T getAttrTemplate(
+            final Class<T> reference, final String schemaName) {
+
+        T result = null;
+
+        for (T template : findInheritedTemplates(reference)) {
+            if (schemaName.equals(template.getSchema().getKey())) {
+                result = template;
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends AttrTemplate<K>, K extends Schema> List<K> getAttrTemplateSchemas(final Class<T> reference) {
+        final List<K> result = new ArrayList<>();
+
+        for (T template : findInheritedTemplates(reference)) {
+            result.add(template.getSchema());
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends AttrTemplate<K>, K extends Schema> List<T> findInheritedTemplates(final Class<T> reference) {
+        final List<T> result = new ArrayList<>(getAttrTemplates(reference));
+
+        if (isInheritTemplates() && getParent() != null) {
+            result.addAll(getParent().findInheritedTemplates(reference));
+        }
+
+        return result;
+    }
+
+    @Override
+    public boolean addPlainAttr(final RPlainAttr attr) {
+        checkType(attr, JPARPlainAttr.class);
+        return plainAttrs.add((JPARPlainAttr) attr);
+    }
+
+    @Override
+    public boolean removePlainAttr(final RPlainAttr attr) {
+        checkType(attr, JPARPlainAttr.class);
+        return plainAttrs.remove((JPARPlainAttr) attr);
+    }
+
+    @Override
+    public List<? extends RPlainAttr> getPlainAttrs() {
+        return plainAttrs;
+    }
+
+    @Override
+    public boolean addDerAttr(final RDerAttr attr) {
+        checkType(attr, JPARDerAttr.class);
+        return derAttrs.add((JPARDerAttr) attr);
+    }
+
+    @Override
+    public boolean removeDerAttr(final RDerAttr attr) {
+        checkType(attr, JPARDerAttr.class);
+        return derAttrs.remove((JPARDerAttr) attr);
+    }
+
+    @Override
+    public List<? extends RDerAttr> getDerAttrs() {
+        return derAttrs;
+    }
+
+    @Override
+    public boolean addVirAttr(final RVirAttr attr) {
+        checkType(attr, JPARVirAttr.class);
+        return virAttrs.add((JPARVirAttr) attr);
+    }
+
+    @Override
+    public boolean removeVirAttr(final RVirAttr attr) {
+        checkType(attr, JPARVirAttr.class);
+        return virAttrs.remove((JPARVirAttr) attr);
+    }
+
+    @Override
+    public List<? extends RVirAttr> getVirAttrs() {
+        return virAttrs;
+    }
+
+    @Override
+    public boolean isInheritAttrs() {
+        return isBooleanAsInteger(inheritAttrs);
+    }
+
+    @Override
+    public void setInheritAttrs(final boolean inheritAttrs) {
+        this.inheritAttrs = getBooleanAsInteger(inheritAttrs);
+    }
+
+    /**
+     * Get all inherited attributes from the ancestors.
+     *
+     * @return a list of inherited and only inherited attributes.
+     */
+    @Override
+    public List<? extends RPlainAttr> findLastInheritedAncestorPlainAttrs() {
+        final Map<JPARPlainSchema, RPlainAttr> result = new HashMap<>();
+
+        if (!isInheritAttrs()) {
+            return plainAttrs;
+        }
+        if (isInheritAttrs() && getParent() != null) {
+            final Map<PlainSchema, RPlainAttr> attrMap = getPlainAttrMap();
+
+            // Add inherit attributes
+            for (RPlainAttr attr : getParent().findLastInheritedAncestorPlainAttrs()) {
+                if (attrMap.containsKey(attr.getSchema())) {
+                    result.remove((JPARPlainSchema) attr.getSchema());
+                }
+                result.put((JPARPlainSchema) attr.getSchema(), attr);
+            }
+        }
+        return new ArrayList<>(result.values());
+    }
+
+    @Override
+    public boolean isInheritDerAttrs() {
+        return isBooleanAsInteger(inheritDerAttrs);
+    }
+
+    @Override
+    public void setInheritDerAttrs(final boolean inheritDerAttrs) {
+        this.inheritDerAttrs = getBooleanAsInteger(inheritDerAttrs);
+
+    }
+
+    /**
+     * Get all inherited derived attributes from the ancestors.
+     *
+     * @return a list of inherited and only inherited attributes.
+     */
+    @Override
+    public List<? extends RDerAttr> findLastInheritedAncestorDerAttrs() {
+        final Map<RDerSchema, RDerAttr> result = new HashMap<>();
+
+        if (!isInheritDerAttrs()) {
+            return derAttrs;
+        }
+        if (isInheritDerAttrs() && getParent() != null) {
+            Map<DerSchema, RDerAttr> derAttrMap = getDerAttrMap();
+
+            // Add inherit derived attributes
+            for (RDerAttr attr : getParent().findLastInheritedAncestorDerAttrs()) {
+                if (derAttrMap.containsKey(attr.getSchema())) {
+                    result.remove(attr.getSchema());
+                }
+                result.put(attr.getSchema(), attr);
+            }
+        }
+        return new ArrayList<>(result.values());
+    }
+
+    @Override
+    public boolean isInheritVirAttrs() {
+        return isBooleanAsInteger(inheritVirAttrs);
+    }
+
+    @Override
+    public void setInheritVirAttrs(final boolean inheritVirAttrs) {
+        this.inheritVirAttrs = getBooleanAsInteger(inheritVirAttrs);
+
+    }
+
+    /**
+     * Get all inherited virtual attributes from the ancestors.
+     *
+     * @return a list of inherited and only inherited attributes.
+     */
+    @Override
+    public List<? extends RVirAttr> findLastInheritedAncestorVirAttrs() {
+        final Map<RVirSchema, RVirAttr> result = new HashMap<>();
+
+        if (!isInheritVirAttrs()) {
+            return virAttrs;
+        }
+
+        if (isInheritVirAttrs() && getParent() != null) {
+            Map<VirSchema, RVirAttr> virAttrMap = getVirAttrMap();
+
+            // Add inherit virtual attributes
+            for (RVirAttr attr : getParent().findLastInheritedAncestorVirAttrs()) {
+                if (virAttrMap.containsKey(attr.getSchema())) {
+                    result.remove(attr.getSchema());
+                }
+                result.put(attr.getSchema(), attr);
+            }
+        }
+        return new ArrayList<>(result.values());
+    }
+
+    /**
+     * Get first valid password policy.
+     *
+     * @return parent password policy if isInheritPasswordPolicy is 'true' and parent is not null, local password policy
+     * otherwise
+     */
+    @Override
+    public PasswordPolicy getPasswordPolicy() {
+        return isInheritPasswordPolicy() && getParent() != null
+                ? getParent().getPasswordPolicy()
+                : passwordPolicy;
+    }
+
+    @Override
+    public void setPasswordPolicy(final PasswordPolicy passwordPolicy) {
+        checkType(passwordPolicy, JPAPasswordPolicy.class);
+        this.passwordPolicy = (JPAPasswordPolicy) passwordPolicy;
+    }
+
+    @Override
+    public boolean isInheritPasswordPolicy() {
+        return isBooleanAsInteger(inheritPasswordPolicy);
+    }
+
+    @Override
+    public void setInheritPasswordPolicy(final boolean inheritPasswordPolicy) {
+        this.inheritPasswordPolicy = getBooleanAsInteger(inheritPasswordPolicy);
+    }
+
+    /**
+     * Get first valid account policy.
+     *
+     * @return parent account policy if isInheritAccountPolicy is 'true' and parent is not null, local account policy
+     * otherwise.
+     */
+    @Override
+    public AccountPolicy getAccountPolicy() {
+        return isInheritAccountPolicy() && getParent() != null
+                ? getParent().getAccountPolicy()
+                : accountPolicy;
+    }
+
+    @Override
+    public void setAccountPolicy(final AccountPolicy accountPolicy) {
+        checkType(accountPolicy, JPAAccountPolicy.class);
+        this.accountPolicy = (JPAAccountPolicy) accountPolicy;
+    }
+
+    @Override
+    public boolean isInheritAccountPolicy() {
+        return isBooleanAsInteger(inheritAccountPolicy);
+    }
+
+    @Override
+    public void setInheritAccountPolicy(boolean inheritAccountPolicy) {
+        this.inheritAccountPolicy = getBooleanAsInteger(inheritAccountPolicy);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/AbstractProvisioningTask.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/AbstractProvisioningTask.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/AbstractProvisioningTask.java
new file mode 100644
index 0000000..7938b01
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/AbstractProvisioningTask.java
@@ -0,0 +1,168 @@
+/*
+ * 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.persistence.jpa.entity.task;
+
+import javax.persistence.Basic;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.ManyToOne;
+import javax.persistence.MappedSuperclass;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import org.apache.syncope.common.lib.types.MatchingRule;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.common.lib.types.UnmatchingRule;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.task.ProvisioningTask;
+import org.apache.syncope.persistence.jpa.validation.entity.ProvisioningTaskCheck;
+import org.apache.syncope.persistence.jpa.entity.JPAExternalResource;
+
+@MappedSuperclass
+@ProvisioningTaskCheck
+public abstract class AbstractProvisioningTask extends JPASchedTask implements ProvisioningTask {
+
+    private static final long serialVersionUID = -4141057723006682562L;
+
+    /**
+     * ExternalResource to which the sync happens.
+     */
+    @ManyToOne
+    private JPAExternalResource resource;
+
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer performCreate;
+
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer performUpdate;
+
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer performDelete;
+
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer syncStatus;
+
+    /**
+     * @see UnmatchingRule
+     */
+    @NotNull
+    @Enumerated(EnumType.STRING)
+    protected UnmatchingRule unmatchingRule;
+
+    /**
+     * @see MatchingRule
+     */
+    @NotNull
+    @Enumerated(EnumType.STRING)
+    protected MatchingRule matchingRule;
+
+    public AbstractProvisioningTask(final TaskType type, final String jobClassName) {
+        super();
+
+        this.type = type;
+        super.setJobClassName(jobClassName);
+    }
+
+    @Override
+    public void setJobClassName(final String jobClassName) {
+        // fixed to SyncJob, cannot be changed
+    }
+
+    @Override
+    public ExternalResource getResource() {
+        return resource;
+    }
+
+    @Override
+    public void setResource(final ExternalResource resource) {
+        checkType(resource, JPAExternalResource.class);
+        this.resource = (JPAExternalResource) resource;
+    }
+
+    @Override
+    public boolean isPerformCreate() {
+        return isBooleanAsInteger(performCreate);
+    }
+
+    @Override
+
+    public void setPerformCreate(final boolean performCreate) {
+        this.performCreate = getBooleanAsInteger(performCreate);
+    }
+
+    @Override
+
+    public boolean isPerformUpdate() {
+        return isBooleanAsInteger(performUpdate);
+    }
+
+    @Override
+
+    public void setPerformUpdate(final boolean performUpdate) {
+        this.performUpdate = getBooleanAsInteger(performUpdate);
+    }
+
+    @Override
+    public boolean isPerformDelete() {
+        return isBooleanAsInteger(performDelete);
+    }
+
+    @Override
+    public void setPerformDelete(boolean performDelete) {
+        this.performDelete = getBooleanAsInteger(performDelete);
+    }
+
+    @Override
+    public boolean isSyncStatus() {
+        return isBooleanAsInteger(syncStatus);
+    }
+
+    @Override
+    public void setSyncStatus(final boolean syncStatus) {
+        this.syncStatus = getBooleanAsInteger(syncStatus);
+    }
+
+    @Override
+    public UnmatchingRule getUnmatchingRule() {
+        return this.unmatchingRule;
+    }
+
+    @Override
+    public void setUnmatchingRule(final UnmatchingRule unmatchigRule) {
+        this.unmatchingRule = unmatchigRule;
+    }
+
+    @Override
+    public MatchingRule getMatchingRule() {
+        return this.matchingRule;
+    }
+
+    @Override
+    public void setMatchingRule(final MatchingRule matchigRule) {
+        this.matchingRule = matchigRule;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPANotificationTask.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPANotificationTask.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPANotificationTask.java
new file mode 100644
index 0000000..6edf99e
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPANotificationTask.java
@@ -0,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.persistence.jpa.entity.task;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Basic;
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.Lob;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.common.lib.types.TraceLevel;
+import org.apache.syncope.persistence.api.entity.task.NotificationTask;
+
+@Entity
+@DiscriminatorValue("NotificationTask")
+public class JPANotificationTask extends JPATask implements NotificationTask {
+
+    private static final long serialVersionUID = 95731573485279180L;
+
+    @ElementCollection(fetch = FetchType.EAGER)
+    @Column(name = "address")
+    @CollectionTable(name = "NotificationTask_recipients",
+            joinColumns =
+            @JoinColumn(name = "NotificationTask_id", referencedColumnName = "id"))
+    private Set<String> recipients;
+
+    @NotNull
+    private String sender;
+
+    @NotNull
+    private String subject;
+
+    @NotNull
+    @Lob
+    private String textBody;
+
+    @NotNull
+    @Lob
+    private String htmlBody;
+
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer executed;
+
+    @Enumerated(EnumType.STRING)
+    @NotNull
+    private TraceLevel traceLevel;
+
+    public JPANotificationTask() {
+        super();
+
+        type = TaskType.NOTIFICATION;
+        recipients = new HashSet<>();
+        executed = getBooleanAsInteger(false);
+    }
+
+    @Override
+    public Set<String> getRecipients() {
+        return recipients;
+    }
+
+    @Override
+    public boolean addRecipient(final String recipient) {
+        return recipients.add(recipient);
+    }
+
+    @Override
+    public boolean removeRecipient(final String recipient) {
+        return recipients.remove(recipient);
+    }
+
+    @Override
+    public String getSender() {
+        return sender;
+    }
+
+    @Override
+    public void setSender(final String sender) {
+        this.sender = sender;
+    }
+
+    @Override
+    public String getSubject() {
+        return subject;
+    }
+
+    @Override
+    public void setSubject(final String subject) {
+        this.subject = subject;
+    }
+
+    @Override
+    public String getTextBody() {
+        return textBody;
+    }
+
+    @Override
+    public void setTextBody(final String textBody) {
+        this.textBody = textBody;
+    }
+
+    @Override
+    public String getHtmlBody() {
+        return htmlBody;
+    }
+
+    @Override
+    public void setHtmlBody(final String htmlBody) {
+        this.htmlBody = htmlBody;
+    }
+
+    @Override
+    public boolean isExecuted() {
+        return isBooleanAsInteger(executed);
+    }
+
+    @Override
+    public void setExecuted(boolean executed) {
+        this.executed = getBooleanAsInteger(executed);
+    }
+
+    @Override
+    public TraceLevel getTraceLevel() {
+        return traceLevel;
+    }
+
+    @Override
+    public void setTraceLevel(final TraceLevel traceLevel) {
+        this.traceLevel = traceLevel;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPAPropagationTask.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPAPropagationTask.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPAPropagationTask.java
new file mode 100644
index 0000000..ec47e59
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPAPropagationTask.java
@@ -0,0 +1,199 @@
+/*
+ * 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.persistence.jpa.entity.task;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Lob;
+import javax.persistence.ManyToOne;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.PropagationMode;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.task.PropagationTask;
+import org.apache.syncope.persistence.jpa.validation.entity.PropagationTaskCheck;
+import org.apache.syncope.persistence.jpa.entity.JPAExternalResource;
+import org.apache.syncope.server.utils.serialization.POJOHelper;
+import org.identityconnectors.framework.common.objects.Attribute;
+
+/**
+ * Encapsulate all information about a propagation task.
+ */
+@Entity
+@DiscriminatorValue("PropagationTask")
+@PropagationTaskCheck
+public class JPAPropagationTask extends JPATask implements PropagationTask {
+
+    private static final long serialVersionUID = 7086054884614511210L;
+
+    /**
+     * @see PropagationMode
+     */
+    @Enumerated(EnumType.STRING)
+    private PropagationMode propagationMode;
+
+    /**
+     * @see ResourceOperation
+     */
+    @Enumerated(EnumType.STRING)
+    private ResourceOperation propagationOperation;
+
+    /**
+     * The accountId on the external resource.
+     */
+    private String accountId;
+
+    /**
+     * The (optional) former accountId on the external resource.
+     */
+    private String oldAccountId;
+
+    /**
+     * Attributes to be propagated.
+     */
+    @Lob
+    private String xmlAttributes;
+
+    private String objectClassName;
+
+    @Enumerated(EnumType.STRING)
+    private AttributableType subjectType;
+
+    private Long subjectId;
+
+    public JPAPropagationTask() {
+        super();
+        type = TaskType.PROPAGATION;
+    }
+
+    /**
+     * ExternalResource to which the propagation happens.
+     */
+    @ManyToOne
+    private JPAExternalResource resource;
+
+    @Override
+    public String getAccountId() {
+        return accountId;
+    }
+
+    @Override
+    public void setAccountId(final String accountId) {
+        this.accountId = accountId;
+    }
+
+    @Override
+    public String getOldAccountId() {
+        return oldAccountId;
+    }
+
+    @Override
+    public void setOldAccountId(final String oldAccountId) {
+        this.oldAccountId = oldAccountId;
+    }
+
+    @Override
+    public Set<Attribute> getAttributes() {
+        return StringUtils.isBlank(xmlAttributes)
+                ? Collections.<Attribute>emptySet()
+                : new HashSet<>(Arrays.asList(POJOHelper.deserialize(xmlAttributes, Attribute[].class)));
+    }
+
+    @Override
+    public void setAttributes(final Set<Attribute> attributes) {
+        xmlAttributes = POJOHelper.serialize(attributes);
+    }
+
+    @Override
+
+    public PropagationMode getPropagationMode() {
+        return propagationMode;
+    }
+
+    @Override
+
+    public void setPropagationMode(final PropagationMode propagationMode) {
+        this.propagationMode = propagationMode;
+    }
+
+    @Override
+
+    public ResourceOperation getPropagationOperation() {
+        return propagationOperation;
+    }
+
+    @Override
+
+    public void setPropagationOperation(final ResourceOperation propagationOperation) {
+        this.propagationOperation = propagationOperation;
+    }
+
+    @Override
+    public ExternalResource getResource() {
+        return resource;
+    }
+
+    @Override
+    public void setResource(final ExternalResource resource) {
+        checkType(resource, JPAExternalResource.class);
+        this.resource = (JPAExternalResource) resource;
+    }
+
+    @Override
+    public String getObjectClassName() {
+        return objectClassName;
+    }
+
+    @Override
+    public void setObjectClassName(final String objectClassName) {
+        this.objectClassName = objectClassName;
+    }
+
+    @Override
+
+    public AttributableType getSubjectType() {
+        return subjectType;
+    }
+
+    @Override
+
+    public void setSubjectType(final AttributableType subjectType) {
+        this.subjectType = subjectType;
+    }
+
+    @Override
+
+    public Long getSubjectId() {
+        return subjectId;
+    }
+
+    @Override
+
+    public void setSubjectId(final Long subjectId) {
+        this.subjectId = subjectId;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPAPushTask.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPAPushTask.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPAPushTask.java
new file mode 100644
index 0000000..d137ef3
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPAPushTask.java
@@ -0,0 +1,82 @@
+/*
+ * 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.persistence.jpa.entity.task;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.persistence.api.entity.task.PushTask;
+import org.apache.syncope.provisioning.api.job.PushJob;
+
+@Entity
+@DiscriminatorValue("PushTask")
+public class JPAPushTask extends AbstractProvisioningTask implements PushTask {
+
+    private static final long serialVersionUID = -4141057723006682564L;
+
+    @ElementCollection(fetch = FetchType.EAGER)
+    @Column(name = "actionClassName")
+    @CollectionTable(name = "PushTask_actionsClassNames",
+            joinColumns =
+            @JoinColumn(name = "PushTask_id", referencedColumnName = "id"))
+    private List<String> actionsClassNames = new ArrayList<>();
+
+    private String userFilter;
+
+    private String roleFilter;
+
+    /**
+     * Default constructor.
+     */
+    public JPAPushTask() {
+        super(TaskType.PUSH, PushJob.class.getName());
+    }
+
+    @Override
+    public List<String> getActionsClassNames() {
+        return actionsClassNames;
+    }
+
+    @Override
+    public String getUserFilter() {
+        return userFilter;
+    }
+
+    @Override
+    public void setUserFilter(final String filter) {
+        this.userFilter = filter;
+    }
+
+    @Override
+    public String getRoleFilter() {
+        return roleFilter;
+    }
+
+    @Override
+    public void setRoleFilter(final String roleFilter) {
+        this.roleFilter = roleFilter;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPASchedTask.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPASchedTask.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPASchedTask.java
new file mode 100644
index 0000000..649664d
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPASchedTask.java
@@ -0,0 +1,89 @@
+/*
+ * 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.persistence.jpa.entity.task;
+
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.Entity;
+import javax.validation.constraints.NotNull;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.persistence.api.entity.task.SchedTask;
+import org.apache.syncope.persistence.jpa.validation.entity.SchedTaskCheck;
+
+@Entity
+@DiscriminatorValue("SchedTask")
+@SchedTaskCheck
+public class JPASchedTask extends JPATask implements SchedTask {
+
+    private static final long serialVersionUID = -4141057723006682562L;
+
+    protected String cronExpression;
+
+    @NotNull
+    protected String jobClassName;
+
+    @NotNull
+    protected String name;
+
+    protected String description;
+
+    public JPASchedTask() {
+        super();
+        this.type = TaskType.SCHEDULED;
+    }
+
+    @Override
+    public String getCronExpression() {
+        return cronExpression;
+    }
+
+    @Override
+    public void setCronExpression(final String cronExpression) {
+        this.cronExpression = cronExpression;
+    }
+
+    @Override
+    public String getJobClassName() {
+        return jobClassName;
+    }
+
+    @Override
+    public void setJobClassName(final String jobClassName) {
+        this.jobClassName = jobClassName;
+    }
+
+    @Override
+    public String getDescription() {
+        return description;
+    }
+
+    @Override
+    public void setDescription(final String description) {
+        this.description = description;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPASyncTask.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPASyncTask.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPASyncTask.java
new file mode 100644
index 0000000..0e0a225
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPASyncTask.java
@@ -0,0 +1,110 @@
+/*
+ * 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.persistence.jpa.entity.task;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.Basic;
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.Lob;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.persistence.api.entity.task.SyncTask;
+import org.apache.syncope.provisioning.api.job.SyncJob;
+import org.apache.syncope.server.utils.serialization.POJOHelper;
+
+@Entity
+@DiscriminatorValue("SyncTask")
+public class JPASyncTask extends AbstractProvisioningTask implements SyncTask {
+
+    private static final long serialVersionUID = -4141057723006682563L;
+
+    @ElementCollection(fetch = FetchType.EAGER)
+    @Column(name = "actionClassName")
+    @CollectionTable(name = "SyncTask_actionsClassNames",
+            joinColumns =
+            @JoinColumn(name = "SyncTask_id", referencedColumnName = "id"))
+    private List<String> actionsClassNames = new ArrayList<>();
+
+    @Lob
+    private String userTemplate;
+
+    @Lob
+    private String roleTemplate;
+
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer fullReconciliation;
+
+    /**
+     * Default constructor.
+     */
+    public JPASyncTask() {
+        super(TaskType.SYNCHRONIZATION, SyncJob.class.getName());
+    }
+
+    @Override
+    public List<String> getActionsClassNames() {
+        return actionsClassNames;
+    }
+
+    @Override
+    public UserTO getUserTemplate() {
+        return userTemplate == null
+                ? new UserTO()
+                : POJOHelper.deserialize(userTemplate, UserTO.class);
+    }
+
+    @Override
+    public void setUserTemplate(final UserTO userTemplate) {
+        this.userTemplate = POJOHelper.serialize(userTemplate);
+    }
+
+    @Override
+    public RoleTO getRoleTemplate() {
+        return userTemplate == null
+                ? new RoleTO()
+                : POJOHelper.deserialize(roleTemplate, RoleTO.class);
+    }
+
+    @Override
+    public void setRoleTemplate(final RoleTO roleTemplate) {
+        this.roleTemplate = POJOHelper.serialize(roleTemplate);
+    }
+
+    @Override
+    public boolean isFullReconciliation() {
+        return isBooleanAsInteger(fullReconciliation);
+    }
+
+    @Override
+    public void setFullReconciliation(final boolean fullReconciliation) {
+        this.fullReconciliation = getBooleanAsInteger(fullReconciliation);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPATask.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPATask.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPATask.java
new file mode 100644
index 0000000..eba6df5
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPATask.java
@@ -0,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.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.persistence.api.entity.task.Task;
+import org.apache.syncope.persistence.api.entity.task.TaskExec;
+import org.apache.syncope.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/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPATaskExec.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPATaskExec.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPATaskExec.java
new file mode 100644
index 0000000..ec29c0b
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/task/JPATaskExec.java
@@ -0,0 +1,82 @@
+/*
+ * 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.persistence.jpa.entity.task;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.task.Task;
+import org.apache.syncope.persistence.api.entity.task.TaskExec;
+import org.apache.syncope.persistence.jpa.entity.AbstractExec;
+
+/**
+ * An execution (with result) of a Task.
+ *
+ * @see JPATask
+ */
+@Entity
+@Table(name = JPATaskExec.TABLE)
+public class JPATaskExec extends AbstractExec implements TaskExec {
+
+    private static final long serialVersionUID = 1909033231464074554L;
+
+    public static final String TABLE = "TaskExec";
+
+    /**
+     * Id.
+     */
+    @Id
+    private Long id;
+
+    /**
+     * The referred task.
+     */
+    @ManyToOne(optional = false)
+    private JPATask task;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public Task getTask() {
+        return task;
+    }
+
+    @Override
+    public void setTask(final Task task) {
+        checkType(task, JPATask.class);
+        this.task = (JPATask) task;
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder(getClass().getSimpleName()).append('{').
+                append("id=").append(id).append(", ").
+                append("startDate=").append(startDate).append(", ").
+                append("endDate=").append(endDate).append(", ").
+                append("task=").append(task).append(", ").
+                append("status=").append(status).append(", ").
+                append("message=").append(message).
+                append('}').
+                toString();
+    }
+}


[22/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUDerAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUDerAttr.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUDerAttr.java
new file mode 100644
index 0000000..868b263
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUDerAttr.java
@@ -0,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.persistence.jpa.entity.user;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.Attributable;
+import org.apache.syncope.persistence.api.entity.DerSchema;
+import org.apache.syncope.persistence.api.entity.user.UDerAttr;
+import org.apache.syncope.persistence.api.entity.user.UDerSchema;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.entity.AbstractDerAttr;
+
+@Entity
+@Table(name = JPAUDerAttr.TABLE)
+public class JPAUDerAttr extends AbstractDerAttr implements UDerAttr {
+
+    private static final long serialVersionUID = 4723044452807292060L;
+
+    public static final String TABLE = "UDerAttr";
+
+    @ManyToOne
+    private JPAUser owner;
+
+    @ManyToOne(fetch = FetchType.EAGER)
+    private JPAUDerSchema derSchema;
+
+    @Override
+    public User getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final Attributable<?, ?, ?> owner) {
+        checkType(owner, JPAUser.class);
+        this.owner = (JPAUser) owner;
+    }
+
+    @Override
+    public UDerSchema getSchema() {
+        return derSchema;
+    }
+
+    @Override
+    public void setSchema(final DerSchema derSchema) {
+        checkType(derSchema, JPAUDerSchema.class);
+        this.derSchema = (JPAUDerSchema) derSchema;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUDerSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUDerSchema.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUDerSchema.java
new file mode 100644
index 0000000..2acf3a3
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUDerSchema.java
@@ -0,0 +1,34 @@
+/*
+ * 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.persistence.jpa.entity.user;
+
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.user.UDerSchema;
+import org.apache.syncope.persistence.jpa.entity.AbstractDerSchema;
+
+@Entity
+@Table(name = JPAUDerSchema.TABLE)
+public class JPAUDerSchema extends AbstractDerSchema implements UDerSchema {
+
+    private static final long serialVersionUID = 6244467775394201229L;
+
+    public static final String TABLE = "UDerSchema";
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUMapping.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUMapping.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUMapping.java
new file mode 100644
index 0000000..f778eeb
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUMapping.java
@@ -0,0 +1,125 @@
+/*
+ * 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.persistence.jpa.entity.user;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.MappingItem;
+import org.apache.syncope.persistence.api.entity.user.UMapping;
+import org.apache.syncope.persistence.api.entity.user.UMappingItem;
+import org.apache.syncope.persistence.jpa.entity.AbstractMapping;
+import org.apache.syncope.persistence.jpa.entity.JPAExternalResource;
+import org.identityconnectors.framework.common.objects.OperationalAttributes;
+
+@Entity
+@Table(name = JPAUMapping.TABLE)
+public class JPAUMapping extends AbstractMapping<UMappingItem> implements UMapping {
+
+    private static final long serialVersionUID = 4285801404504561073L;
+
+    public static final String TABLE = "UMapping";
+
+    @Id
+    private Long id;
+
+    /**
+     * Resource owning this mapping.
+     */
+    @OneToOne
+    private JPAExternalResource resource;
+
+    /**
+     * Attribute mappings.
+     */
+    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "mapping")
+    private List<JPAUMappingItem> items;
+
+    public JPAUMapping() {
+        super();
+
+        items = new ArrayList<>();
+    }
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public ExternalResource getResource() {
+        return resource;
+    }
+
+    @Override
+    public void setResource(final ExternalResource resource) {
+        checkType(resource, JPAExternalResource.class);
+        this.resource = (JPAExternalResource) resource;
+    }
+
+    @Override
+    public void setAccountIdItem(final UMappingItem item) {
+        checkType(item, JPAUMappingItem.class);
+        this.addAccountIdItem((JPAUMappingItem) item);
+    }
+
+    @Override
+    public UMappingItem getPasswordItem() {
+        UMappingItem passwordItem = null;
+        for (MappingItem item : getItems()) {
+            if (item.isPassword()) {
+                passwordItem = (JPAUMappingItem) item;
+            }
+        }
+        return passwordItem;
+    }
+
+    @Override
+    public boolean setPasswordItem(final UMappingItem passwordItem) {
+        checkType(passwordItem, JPAUMappingItem.class);
+
+        passwordItem.setExtAttrName(OperationalAttributes.PASSWORD_NAME);
+        passwordItem.setPassword(true);
+        return this.addItem((JPAUMappingItem) passwordItem);
+    }
+
+    @Override
+    public List<? extends UMappingItem> getItems() {
+        return items;
+    }
+
+    @Override
+    public boolean addItem(final UMappingItem item) {
+        checkType(item, JPAUMappingItem.class);
+        return items.contains((JPAUMappingItem) item) || items.add((JPAUMappingItem) item);
+    }
+
+    @Override
+    public boolean removeItem(final UMappingItem item) {
+        checkType(item, JPAUMappingItem.class);
+        return items.remove((JPAUMappingItem) item);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUMappingItem.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUMappingItem.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUMappingItem.java
new file mode 100644
index 0000000..47aa4e9
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUMappingItem.java
@@ -0,0 +1,58 @@
+/*
+ * 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.persistence.jpa.entity.user;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.Mapping;
+import org.apache.syncope.persistence.api.entity.user.UMappingItem;
+import org.apache.syncope.persistence.jpa.entity.AbstractMappingItem;
+
+@Entity
+@Table(name = JPAUMappingItem.TABLE)
+public class JPAUMappingItem extends AbstractMappingItem implements UMappingItem {
+
+    private static final long serialVersionUID = 2936446317887310833L;
+
+    public static final String TABLE = "UMappingItem";
+
+    @Id
+    private Long id;
+
+    @ManyToOne
+    private JPAUMapping mapping;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public Mapping<UMappingItem> getMapping() {
+        return mapping;
+    }
+
+    @Override
+    public void setMapping(final Mapping<?> mapping) {
+        checkType(mapping, JPAUMapping.class);
+        this.mapping = (JPAUMapping) mapping;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUPlainAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUPlainAttr.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUPlainAttr.java
new file mode 100644
index 0000000..7f32ae3
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUPlainAttr.java
@@ -0,0 +1,147 @@
+/*
+ * 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.persistence.jpa.entity.user;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.validation.Valid;
+import org.apache.syncope.persistence.api.entity.Attributable;
+import org.apache.syncope.persistence.api.entity.PlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttr;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttrValue;
+import org.apache.syncope.persistence.api.entity.user.UPlainSchema;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainAttr;
+
+@Entity
+@Table(name = JPAUPlainAttr.TABLE)
+public class JPAUPlainAttr extends AbstractPlainAttr implements UPlainAttr {
+
+    private static final long serialVersionUID = 6333601983691157406L;
+
+    public static final String TABLE = "UPlainAttr";
+
+    /**
+     * Auto-generated id for this table.
+     */
+    @Id
+    private Long id;
+
+    /**
+     * The owner of this attribute.
+     */
+    @ManyToOne(fetch = FetchType.EAGER)
+    private JPAUser owner;
+
+    /**
+     * The schema of this attribute.
+     */
+    @ManyToOne(fetch = FetchType.EAGER)
+    @JoinColumn(name = "schema_name")
+    private JPAUPlainSchema schema;
+
+    /**
+     * Values of this attribute (if schema is not UNIQUE).
+     */
+    @OneToMany(cascade = CascadeType.MERGE, orphanRemoval = true, mappedBy = "attribute")
+    @Valid
+    private List<JPAUPlainAttrValue> values;
+
+    /**
+     * Value of this attribute (if schema is UNIQUE).
+     */
+    @OneToOne(cascade = CascadeType.ALL, mappedBy = "attribute")
+    @Valid
+    private JPAUPlainAttrUniqueValue uniqueValue;
+
+    /**
+     * Default constructor.
+     */
+    public JPAUPlainAttr() {
+        super();
+        values = new ArrayList<>();
+    }
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public User getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final Attributable<?, ?, ?> owner) {
+        checkType(owner, JPAUser.class);
+        this.owner = (JPAUser) owner;
+    }
+
+    @Override
+    public UPlainSchema getSchema() {
+        return schema;
+    }
+
+    @Override
+    public void setSchema(final PlainSchema schema) {
+        checkType(schema, JPAUPlainSchema.class);
+        this.schema = (JPAUPlainSchema) schema;
+    }
+
+    @Override
+    protected boolean addValue(final PlainAttrValue attrValue) {
+        checkType(attrValue, JPAUPlainAttrValue.class);
+        return values.add((JPAUPlainAttrValue) attrValue);
+    }
+
+    @Override
+    public boolean removeValue(final PlainAttrValue attrValue) {
+        checkType(attrValue, JPAUPlainAttrValue.class);
+        return values.remove((JPAUPlainAttrValue) attrValue);
+    }
+
+    @Override
+    public List<? extends UPlainAttrValue> getValues() {
+        return values;
+    }
+
+    @Override
+    public UPlainAttrUniqueValue getUniqueValue() {
+        return uniqueValue;
+    }
+
+    @Override
+    public void setUniqueValue(final PlainAttrUniqueValue uniqueValue) {
+        checkType(uniqueValue, JPAUPlainAttrUniqueValue.class);
+        this.uniqueValue = (JPAUPlainAttrUniqueValue) uniqueValue;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUPlainAttrUniqueValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUPlainAttrUniqueValue.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUPlainAttrUniqueValue.java
new file mode 100644
index 0000000..d65c569
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUPlainAttrUniqueValue.java
@@ -0,0 +1,79 @@
+/*
+ * 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.persistence.jpa.entity.user;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttr;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.user.UPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainAttrValue;
+
+@Entity
+@Table(name = JPAUPlainAttrUniqueValue.TABLE)
+public class JPAUPlainAttrUniqueValue extends AbstractPlainAttrValue implements UPlainAttrUniqueValue {
+
+    private static final long serialVersionUID = -64080804563305387L;
+
+    public static final String TABLE = "UPlainAttrUniqueValue";
+
+    @Id
+    private Long id;
+
+    @OneToOne(optional = false)
+    private JPAUPlainAttr attribute;
+
+    @ManyToOne(optional = false)
+    @JoinColumn(name = "schema_name")
+    private JPAUPlainSchema schema;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public UPlainAttr getAttr() {
+        return attribute;
+    }
+
+    @Override
+    public void setAttr(final PlainAttr attr) {
+        checkType(attr, JPAUPlainAttr.class);
+        this.attribute = (JPAUPlainAttr) attr;
+    }
+
+    @Override
+    public UPlainSchema getSchema() {
+        return schema;
+    }
+
+    @Override
+    public void setSchema(final PlainSchema schema) {
+        checkType(schema, JPAUPlainSchema.class);
+        this.schema = (JPAUPlainSchema) schema;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUPlainAttrValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUPlainAttrValue.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUPlainAttrValue.java
new file mode 100644
index 0000000..6f97915
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUPlainAttrValue.java
@@ -0,0 +1,64 @@
+/*
+ * 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.persistence.jpa.entity.user;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttr;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttrValue;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainAttrValue;
+
+@Entity
+@Table(name = JPAUPlainAttrValue.TABLE)
+@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
+public class JPAUPlainAttrValue extends AbstractPlainAttrValue implements UPlainAttrValue {
+
+    private static final long serialVersionUID = -6259576015647897446L;
+
+    public static final String TABLE = "UPlainAttrValue";
+
+    @Id
+    private Long id;
+
+    @ManyToOne
+    @NotNull
+    private JPAUPlainAttr attribute;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public UPlainAttr getAttr() {
+        return attribute;
+    }
+
+    @Override
+    public void setAttr(final PlainAttr attr) {
+        checkType(attr, JPAUPlainAttr.class);
+        this.attribute = (JPAUPlainAttr) attr;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUPlainSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUPlainSchema.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUPlainSchema.java
new file mode 100644
index 0000000..1054a59
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUPlainSchema.java
@@ -0,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.persistence.jpa.entity.user;
+
+import javax.persistence.Cacheable;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.user.UPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainSchema;
+
+@Entity
+@Table(name = JPAUPlainSchema.TABLE)
+@Cacheable
+public class JPAUPlainSchema extends AbstractPlainSchema implements UPlainSchema {
+
+    public static final String TABLE = "UPlainSchema";
+
+    private static final long serialVersionUID = -7272127460142463237L;
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUVirAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUVirAttr.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUVirAttr.java
new file mode 100644
index 0000000..06770d5
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUVirAttr.java
@@ -0,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.persistence.jpa.entity.user;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.Attributable;
+import org.apache.syncope.persistence.api.entity.VirSchema;
+import org.apache.syncope.persistence.api.entity.user.UVirAttr;
+import org.apache.syncope.persistence.api.entity.user.UVirSchema;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.entity.AbstractVirAttr;
+
+@Entity
+@Table(name = JPAUVirAttr.TABLE)
+public class JPAUVirAttr extends AbstractVirAttr implements UVirAttr {
+
+    private static final long serialVersionUID = 2943450934283989741L;
+
+    public static final String TABLE = "UVirAttr";
+
+    @ManyToOne
+    private JPAUser owner;
+
+    @ManyToOne(fetch = FetchType.EAGER)
+    private JPAUVirSchema virSchema;
+
+    @Override
+    public User getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final Attributable<?, ?, ?> owner) {
+        checkType(owner, JPAUser.class);
+        this.owner = (JPAUser) owner;
+    }
+
+    @Override
+    public UVirSchema getSchema() {
+        return virSchema;
+    }
+
+    @Override
+    public void setSchema(final VirSchema virSchema) {
+        checkType(virSchema, JPAUVirSchema.class);
+        this.virSchema = (JPAUVirSchema) virSchema;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUVirSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUVirSchema.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUVirSchema.java
new file mode 100644
index 0000000..abf3635
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUVirSchema.java
@@ -0,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.persistence.jpa.entity.user;
+
+import javax.persistence.Cacheable;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.user.UVirSchema;
+import org.apache.syncope.persistence.jpa.entity.AbstractVirSchema;
+
+@Entity
+@Table(name = JPAUVirSchema.TABLE)
+@Cacheable
+public class JPAUVirSchema extends AbstractVirSchema implements UVirSchema {
+
+    private static final long serialVersionUID = 1089308700791426201L;
+
+    public static final String TABLE = "UVirSchema";
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUser.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUser.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUser.java
new file mode 100644
index 0000000..ec28d6c
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/user/JPAUser.java
@@ -0,0 +1,536 @@
+/*
+ * 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.persistence.jpa.entity.user;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import javax.persistence.Basic;
+import javax.persistence.Cacheable;
+import javax.persistence.CascadeType;
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.Lob;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.persistence.Transient;
+import javax.validation.Valid;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import org.apache.syncope.common.lib.types.CipherAlgorithm;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.membership.Membership;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.api.entity.user.SecurityQuestion;
+import org.apache.syncope.persistence.api.entity.user.UDerAttr;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttr;
+import org.apache.syncope.persistence.api.entity.user.UVirAttr;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.validation.entity.UserCheck;
+import org.apache.syncope.persistence.jpa.entity.AbstractSubject;
+import org.apache.syncope.persistence.jpa.entity.JPAExternalResource;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMembership;
+import org.apache.syncope.server.security.Encryptor;
+import org.apache.syncope.server.security.SecureRandomUtil;
+
+/**
+ * Syncope user bean.
+ */
+@Entity
+@Table(name = JPAUser.TABLE)
+@Cacheable
+@UserCheck
+public class JPAUser extends AbstractSubject<UPlainAttr, UDerAttr, UVirAttr> implements User {
+
+    private static final long serialVersionUID = -3905046855521446823L;
+
+    public static final String TABLE = "SyncopeUser";
+
+    @Id
+    private Long id;
+
+    @Column(nullable = true)
+    private String password;
+
+    @Transient
+    private String clearPassword;
+
+    @OneToMany(cascade = CascadeType.MERGE, mappedBy = "user")
+    @Valid
+    private List<JPAMembership> memberships;
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPAUPlainAttr> plainAttrs;
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPAUDerAttr> derAttrs;
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPAUVirAttr> virAttrs;
+
+    private String workflowId;
+
+    @Column(nullable = true)
+    private String status;
+
+    @Lob
+    private String token;
+
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date tokenExpireTime;
+
+    @Column(nullable = true)
+    @Enumerated(EnumType.STRING)
+    private CipherAlgorithm cipherAlgorithm;
+
+    @ElementCollection
+    @Column(name = "passwordHistoryValue")
+    @CollectionTable(name = "SyncopeUser_passwordHistory",
+            joinColumns =
+            @JoinColumn(name = "SyncopeUser_id", referencedColumnName = "id"))
+    private List<String> passwordHistory;
+
+    /**
+     * Subsequent failed logins.
+     */
+    @Column(nullable = true)
+    private Integer failedLogins;
+
+    /**
+     * Username/Login.
+     */
+    @Column(unique = true)
+    @NotNull(message = "Blank username")
+    private String username;
+
+    /**
+     * Last successful login date.
+     */
+    @Column(nullable = true)
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date lastLoginDate;
+
+    /**
+     * Change password date.
+     */
+    @Column(nullable = true)
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date changePwdDate;
+
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer suspended;
+
+    /**
+     * Provisioning external resources.
+     */
+    @ManyToMany(fetch = FetchType.EAGER)
+    @JoinTable(joinColumns =
+            @JoinColumn(name = "user_id"),
+            inverseJoinColumns =
+            @JoinColumn(name = "resource_name"))
+    @Valid
+    private Set<JPAExternalResource> resources;
+
+    @ManyToOne(fetch = FetchType.EAGER, optional = true)
+    private SecurityQuestion securityQuestion;
+
+    @Column(nullable = true)
+    private String securityAnswer;
+
+    public JPAUser() {
+        super();
+
+        memberships = new ArrayList<>();
+        plainAttrs = new ArrayList<>();
+        derAttrs = new ArrayList<>();
+        virAttrs = new ArrayList<>();
+        passwordHistory = new ArrayList<>();
+        failedLogins = 0;
+        suspended = getBooleanAsInteger(Boolean.FALSE);
+        resources = new HashSet<>();
+    }
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    protected Set<? extends ExternalResource> internalGetResources() {
+        return resources;
+    }
+
+    @Override
+    public boolean addMembership(final Membership membership) {
+        checkType(membership, JPAMembership.class);
+        return memberships.contains((JPAMembership) membership) || memberships.add((JPAMembership) membership);
+    }
+
+    @Override
+    public boolean removeMembership(final Membership membership) {
+        return memberships.remove(membership);
+    }
+
+    @Override
+    public Membership getMembership(final Long syncopeRoleId) {
+        Membership result = null;
+        Membership membership;
+        for (Iterator<? extends Membership> itor = getMemberships().iterator(); result == null && itor.hasNext();) {
+            membership = itor.next();
+            if (membership.getRole() != null && syncopeRoleId.equals(membership.getRole().getKey())) {
+                result = membership;
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public List<? extends Membership> getMemberships() {
+        return memberships;
+    }
+
+    @Override
+    public List<Role> getRoles() {
+        List<Role> result = new ArrayList<>();
+
+        for (Membership membership : memberships) {
+            if (membership.getRole() != null) {
+                result.add(membership.getRole());
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public Set<Long> getRoleIds() {
+        List<Role> roles = getRoles();
+
+        Set<Long> result = new HashSet<>(roles.size());
+        for (Role role : roles) {
+            result.add(role.getKey());
+        }
+
+        return result;
+    }
+
+    @Override
+    public Set<ExternalResource> getResources() {
+        Set<ExternalResource> result = new HashSet<>();
+        result.addAll(super.getResources());
+        for (Role role : getRoles()) {
+            result.addAll(role.getResources());
+        }
+
+        return result;
+    }
+
+    @Override
+    public Set<? extends ExternalResource> getOwnResources() {
+        return super.getResources();
+    }
+
+    @Override
+    public String getPassword() {
+        return password;
+    }
+
+    @Override
+    public String getClearPassword() {
+        return clearPassword;
+    }
+
+    @Override
+    public void removeClearPassword() {
+        clearPassword = null;
+    }
+
+    @Override
+    public void setEncodedPassword(final String password, final CipherAlgorithm cipherAlgoritm) {
+        // clear password
+        this.clearPassword = null;
+
+        this.password = password;
+        this.cipherAlgorithm = cipherAlgoritm;
+    }
+
+    @Override
+    public void setPassword(final String password, final CipherAlgorithm cipherAlgoritm) {
+        // clear password
+        this.clearPassword = password;
+
+        try {
+            this.password = Encryptor.getInstance().encode(password, cipherAlgoritm);
+            this.cipherAlgorithm = cipherAlgoritm;
+        } catch (Exception e) {
+            LOG.error("Could not encode password", e);
+            this.password = null;
+        }
+    }
+
+    @Override
+    public CipherAlgorithm getCipherAlgorithm() {
+        return cipherAlgorithm;
+    }
+
+    @Override
+    public boolean canDecodePassword() {
+        return this.cipherAlgorithm != null && this.cipherAlgorithm.isInvertible();
+    }
+
+    @Override
+    public boolean addPlainAttr(final UPlainAttr attr) {
+        checkType(attr, JPAUPlainAttr.class);
+        return plainAttrs.add((JPAUPlainAttr) attr);
+    }
+
+    @Override
+    public boolean removePlainAttr(final UPlainAttr attr) {
+        checkType(attr, JPAUPlainAttr.class);
+        return plainAttrs.remove((JPAUPlainAttr) attr);
+    }
+
+    @Override
+    public List<? extends UPlainAttr> getPlainAttrs() {
+        return plainAttrs;
+    }
+
+    @Override
+    public boolean addDerAttr(final UDerAttr attr) {
+        checkType(attr, JPAUDerAttr.class);
+        return derAttrs.add((JPAUDerAttr) attr);
+    }
+
+    @Override
+    public boolean removeDerAttr(final UDerAttr attr) {
+        checkType(attr, JPAUDerAttr.class);
+        return derAttrs.remove((JPAUDerAttr) attr);
+    }
+
+    @Override
+    public List<? extends UDerAttr> getDerAttrs() {
+        return derAttrs;
+    }
+
+    @Override
+    public boolean addVirAttr(final UVirAttr attr) {
+        checkType(attr, JPAUVirAttr.class);
+        return virAttrs.add((JPAUVirAttr) attr);
+    }
+
+    @Override
+    public boolean removeVirAttr(final UVirAttr attr) {
+        checkType(attr, JPAUVirAttr.class);
+        return virAttrs.remove((JPAUVirAttr) attr);
+    }
+
+    @Override
+    public List<? extends UVirAttr> getVirAttrs() {
+        return virAttrs;
+    }
+
+    @Override
+    public String getWorkflowId() {
+        return workflowId;
+    }
+
+    @Override
+    public void setWorkflowId(final String workflowId) {
+        this.workflowId = workflowId;
+    }
+
+    @Override
+    public String getStatus() {
+        return status;
+    }
+
+    @Override
+    public void setStatus(final String status) {
+        this.status = status;
+    }
+
+    @Override
+    public void generateToken(final int tokenLength, final int tokenExpireTime) {
+        this.token = SecureRandomUtil.generateRandomPassword(tokenLength);
+
+        Calendar calendar = Calendar.getInstance();
+        calendar.add(Calendar.MINUTE, tokenExpireTime);
+        this.tokenExpireTime = calendar.getTime();
+    }
+
+    @Override
+    public void removeToken() {
+        this.token = null;
+        this.tokenExpireTime = null;
+    }
+
+    @Override
+    public String getToken() {
+        return token;
+    }
+
+    @Override
+    public Date getTokenExpireTime() {
+        return tokenExpireTime == null
+                ? null
+                : new Date(tokenExpireTime.getTime());
+    }
+
+    @Override
+    public boolean checkToken(final String token) {
+        return this.token == null || this.token.equals(token) && !hasTokenExpired();
+    }
+
+    @Override
+    public boolean hasTokenExpired() {
+        return tokenExpireTime == null
+                ? false
+                : tokenExpireTime.before(new Date());
+    }
+
+    @Override
+    public void setCipherAlgorithm(final CipherAlgorithm cipherAlgorithm) {
+        this.cipherAlgorithm = cipherAlgorithm;
+    }
+
+    @Override
+    public List<String> getPasswordHistory() {
+        return passwordHistory;
+    }
+
+    @Override
+    public Date getChangePwdDate() {
+        return changePwdDate == null
+                ? null
+                : new Date(changePwdDate.getTime());
+    }
+
+    @Override
+    public void setChangePwdDate(final Date changePwdDate) {
+        this.changePwdDate = changePwdDate == null
+                ? null
+                : new Date(changePwdDate.getTime());
+    }
+
+    @Override
+    public Integer getFailedLogins() {
+        return failedLogins == null ? 0 : failedLogins;
+    }
+
+    @Override
+    public void setFailedLogins(final Integer failedLogins) {
+        this.failedLogins = failedLogins;
+    }
+
+    @Override
+    public Date getLastLoginDate() {
+        return lastLoginDate == null
+                ? null
+                : new Date(lastLoginDate.getTime());
+    }
+
+    @Override
+    public void setLastLoginDate(final Date lastLoginDate) {
+        this.lastLoginDate = lastLoginDate == null
+                ? null
+                : new Date(lastLoginDate.getTime());
+    }
+
+    @Override
+    public String getUsername() {
+        return username;
+    }
+
+    @Override
+    public void setUsername(final String username) {
+        this.username = username;
+    }
+
+    @Override
+    public void setSuspended(final Boolean suspended) {
+        this.suspended = getBooleanAsInteger(suspended);
+    }
+
+    @Override
+    public Boolean isSuspended() {
+        return suspended == null ? null : isBooleanAsInteger(suspended);
+    }
+
+    @Override
+    public boolean verifyPasswordHistory(final String password, final int size) {
+        boolean res = false;
+
+        if (size > 0) {
+            try {
+                res = passwordHistory.subList(size >= passwordHistory.size()
+                        ? 0
+                        : passwordHistory.size() - size, passwordHistory.size()).contains(cipherAlgorithm == null
+                                        ? password
+                                        : Encryptor.getInstance().encode(password, cipherAlgorithm));
+            } catch (Exception e) {
+                LOG.error("Error evaluating password history", e);
+            }
+        }
+
+        return res;
+    }
+
+    @Override
+    public SecurityQuestion getSecurityQuestion() {
+        return securityQuestion;
+    }
+
+    @Override
+    public void setSecurityQuestion(final SecurityQuestion securityQuestion) {
+        this.securityQuestion = securityQuestion;
+    }
+
+    @Override
+    public String getSecurityAnswer() {
+        return securityAnswer;
+    }
+
+    @Override
+    public void setSecurityAnswer(final String securityAnswer) {
+        this.securityAnswer = securityAnswer;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/AbstractValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/AbstractValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/AbstractValidator.java
new file mode 100644
index 0000000..6ebfb15
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/AbstractValidator.java
@@ -0,0 +1,46 @@
+/*
+ * 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.persistence.jpa.validation.entity;
+
+import java.lang.annotation.Annotation;
+import java.util.regex.Pattern;
+import javax.validation.ConstraintValidator;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractValidator<A extends Annotation, T> implements ConstraintValidator<A, T> {
+
+    /**
+     * Logger.
+     */
+    protected static final Logger LOG = LoggerFactory.getLogger(AbstractValidator.class);
+
+    protected static final Pattern NAME_PATTERN =
+            Pattern.compile("^[\\w \\-@.]+", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
+
+    @Override
+    public void initialize(final A annotation) {
+        // no initialization
+    }
+
+    protected final String getTemplate(final EntityViolationType type, final String message) {
+        return type.name() + ";" + message;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ConnInstanceCheck.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ConnInstanceCheck.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ConnInstanceCheck.java
new file mode 100644
index 0000000..f96cd8f
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ConnInstanceCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.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 = ConnInstanceValidator.class)
+@Documented
+public @interface ConnInstanceCheck {
+
+    String message() default "{org.apache.syncope.persistence.validation.connninstance}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ConnInstanceValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ConnInstanceValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ConnInstanceValidator.java
new file mode 100644
index 0000000..ba60ae4
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ConnInstanceValidator.java
@@ -0,0 +1,64 @@
+/*
+ * 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.persistence.jpa.validation.entity;
+
+import javax.validation.ConstraintValidatorContext;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.persistence.api.entity.ConnInstance;
+import org.apache.syncope.persistence.jpa.entity.JPAConnPoolConf;
+import org.apache.syncope.server.utils.URIUtil;
+import org.apache.syncope.provisioning.api.ConnPoolConfUtil;
+
+public class ConnInstanceValidator extends AbstractValidator<ConnInstanceCheck, ConnInstance> {
+
+    @Override
+    public boolean isValid(final ConnInstance connInstance, final ConstraintValidatorContext context) {
+        boolean isValid = true;
+
+        try {
+            URIUtil.buildForConnId(connInstance.getLocation());
+        } catch (Exception e) {
+            LOG.error("While validating {}", connInstance.getLocation(), e);
+
+            context.disableDefaultConstraintViolation();
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidConnInstanceLocation, e.getMessage())).
+                    addPropertyNode("location").addConstraintViolation();
+
+            isValid = false;
+        }
+
+        if (isValid && connInstance.getPoolConf() != null) {
+            try {
+                ConnPoolConfUtil.getObjectPoolConfiguration(connInstance.getPoolConf()).validate();
+            } catch (Exception e) {
+                LOG.error("Invalid pool configuration", e);
+
+                context.disableDefaultConstraintViolation();
+                context.buildConstraintViolationWithTemplate(
+                        getTemplate(EntityViolationType.InvalidConnPoolConf, e.getMessage())).
+                        addPropertyNode("poolConf").addConstraintViolation();
+
+                isValid = false;
+            }
+        }
+
+        return isValid;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/EntityValidationListener.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/EntityValidationListener.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/EntityValidationListener.java
new file mode 100644
index 0000000..4836e87
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/EntityValidationListener.java
@@ -0,0 +1,51 @@
+/*
+ * 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.persistence.jpa.validation.entity;
+
+import java.util.Set;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import javax.validation.ConstraintViolation;
+import javax.validation.Validator;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.server.spring.ApplicationContextProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * JPA validation listener implementing bean validation.
+ */
+public class EntityValidationListener {
+
+    /**
+     * Logger.
+     */
+    private static final Logger LOG = LoggerFactory.getLogger(EntityValidationListener.class);
+
+    @PrePersist
+    @PreUpdate
+    public void validate(final Object object) {
+        final Validator validator = ApplicationContextProvider.getApplicationContext().getBean(Validator.class);
+        Set<ConstraintViolation<Object>> violations = validator.validate(object);
+        if (!violations.isEmpty()) {
+            LOG.warn("Bean validation errors found: {}", violations);
+            throw new InvalidEntityException(object.getClass().getSimpleName(), violations);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ExternalResourceCheck.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ExternalResourceCheck.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ExternalResourceCheck.java
new file mode 100644
index 0000000..f2f3843
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ExternalResourceCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.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 = ExternalResourceValidator.class)
+@Documented
+public @interface ExternalResourceCheck {
+
+    String message() default "{org.apache.syncope.persistence.validation.externalresource}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ExternalResourceValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ExternalResourceValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ExternalResourceValidator.java
new file mode 100644
index 0000000..db4fb94
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ExternalResourceValidator.java
@@ -0,0 +1,130 @@
+/*
+ * 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.persistence.jpa.validation.entity;
+
+import javax.validation.ConstraintValidatorContext;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.Mapping;
+import org.apache.syncope.persistence.api.entity.MappingItem;
+import org.apache.syncope.provisioning.api.propagation.PropagationActions;
+
+public class ExternalResourceValidator extends AbstractValidator<ExternalResourceCheck, ExternalResource> {
+
+    private boolean isValid(final MappingItem item, final ConstraintValidatorContext context) {
+        if (StringUtils.isBlank(item.getExtAttrName())) {
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidMapping, item + ".extAttrName is null")).
+                    addPropertyNode("extAttrName").addConstraintViolation();
+
+            return false;
+        }
+
+        if (StringUtils.isBlank(item.getIntAttrName())) {
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidMapping, item + ".intAttrName is null")).
+                    addPropertyNode("intAttrName").addConstraintViolation();
+
+            return false;
+        }
+
+        if (item.getPurpose() == null) {
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidMapping, item + ".purpose is null")).
+                    addPropertyNode("purpose").addConstraintViolation();
+
+            return false;
+        }
+
+        return true;
+    }
+
+    private boolean isValid(final Mapping<?> mapping, final ConstraintValidatorContext context) {
+        if (mapping == null) {
+            return true;
+        }
+
+        int accountIds = 0;
+        for (MappingItem item : mapping.getItems()) {
+            if (item.isAccountid()) {
+                accountIds++;
+            }
+        }
+        if (accountIds != 1) {
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidMapping, "One and only one accountId mapping is needed")).
+                    addPropertyNode("accountId.size").addConstraintViolation();
+            return false;
+        }
+
+        boolean isValid = true;
+
+        int passwords = 0;
+        for (MappingItem item : mapping.getItems()) {
+            isValid &= isValid(item, context);
+
+            if (item.isPassword()) {
+                passwords++;
+            }
+        }
+        if (passwords > 1) {
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidMapping, "One and only one password mapping is allowed")).
+                    addPropertyNode("password.size").addConstraintViolation();
+            isValid = false;
+        }
+
+        return isValid;
+    }
+
+    @Override
+    public boolean isValid(final ExternalResource resource, final ConstraintValidatorContext context) {
+        context.disableDefaultConstraintViolation();
+
+        if (!NAME_PATTERN.matcher(resource.getKey()).matches()) {
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidName, "Invalid Resource name")).
+                    addPropertyNode("name").addConstraintViolation();
+            return false;
+        }
+
+        if (!resource.getPropagationActionsClassNames().isEmpty()) {
+            for (String className : resource.getPropagationActionsClassNames()) {
+                Class<?> actionsClass = null;
+                boolean isAssignable = false;
+                try {
+                    actionsClass = Class.forName(className);
+                    isAssignable = PropagationActions.class.isAssignableFrom(actionsClass);
+                } catch (Exception e) {
+                    LOG.error("Invalid PropagationActions specified: {}", className, e);
+                }
+
+                if (actionsClass == null || !isAssignable) {
+                    context.buildConstraintViolationWithTemplate(
+                            getTemplate(EntityViolationType.InvalidResource, "Invalid actions class name")).
+                            addPropertyNode("actionsClassName").addConstraintViolation();
+                    return false;
+                }
+            }
+        }
+
+        return isValid(resource.getUmapping(), context) && isValid(resource.getRmapping(), context);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/NotificationCheck.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/NotificationCheck.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/NotificationCheck.java
new file mode 100644
index 0000000..cee0bde
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/NotificationCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.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 = NotificationValidator.class)
+@Documented
+public @interface NotificationCheck {
+
+    String message() default "{org.apache.syncope.persistence.validation.notification}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/NotificationValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/NotificationValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/NotificationValidator.java
new file mode 100644
index 0000000..fe815c8
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/NotificationValidator.java
@@ -0,0 +1,59 @@
+/*
+ * 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.persistence.jpa.validation.entity;
+
+import java.util.regex.Matcher;
+import javax.validation.ConstraintValidatorContext;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.persistence.api.entity.Notification;
+
+public class NotificationValidator extends AbstractValidator<NotificationCheck, Notification> {
+
+    @Override
+    public boolean isValid(final Notification value, final ConstraintValidatorContext context) {
+        context.disableDefaultConstraintViolation();
+
+        boolean isValid = true;
+
+        if (value.getEvents().isEmpty()) {
+            isValid = false;
+
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidNotification, "No events")).
+                    addPropertyNode("events").addConstraintViolation();
+        }
+
+        if (!value.getStaticRecipients().isEmpty()) {
+            for (String mail : value.getStaticRecipients()) {
+                Matcher matcher = SyncopeConstants.EMAIL_PATTERN.matcher(mail);
+                if (!matcher.matches()) {
+                    LOG.error("Invalid mail address: {}", mail);
+                    isValid = false;
+
+                    context.buildConstraintViolationWithTemplate(
+                            getTemplate(EntityViolationType.InvalidNotification, "Invalid mail address: " + mail)).
+                            addPropertyNode("staticRecipients").addConstraintViolation();
+                }
+            }
+        }
+
+        return isValid;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainAttrCheck.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainAttrCheck.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainAttrCheck.java
new file mode 100644
index 0000000..4381013
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainAttrCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.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 = PlainAttrValidator.class)
+@Documented
+public @interface PlainAttrCheck {
+
+    String message() default "{org.apache.syncope.syncope.validation.attr}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainAttrValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainAttrValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainAttrValidator.java
new file mode 100644
index 0000000..88fcbfc
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainAttrValidator.java
@@ -0,0 +1,59 @@
+/*
+ * 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.persistence.jpa.validation.entity;
+
+import javax.validation.ConstraintValidatorContext;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+
+public class PlainAttrValidator extends AbstractValidator<PlainAttrCheck, PlainAttr> {
+
+    @Override
+    public boolean isValid(final PlainAttr object, final ConstraintValidatorContext context) {
+        boolean isValid;
+
+        if (object == null) {
+            isValid = true;
+        } else {
+            if (object.getSchema().isUniqueConstraint()) {
+                isValid = object.getValues().isEmpty() && object.getUniqueValue() != null;
+            } else {
+                isValid = !object.getValues().isEmpty() && object.getUniqueValue() == null;
+
+                if (!object.getSchema().isMultivalue()) {
+                    isValid &= object.getValues().size() == 1;
+                }
+            }
+
+            if (!isValid) {
+                LOG.error("Invalid values for attribute " + object + ": " + "schema=" + object.getSchema().getKey()
+                        + ", " + "values={}", object.getValuesAsStrings());
+
+                context.disableDefaultConstraintViolation();
+
+                context.buildConstraintViolationWithTemplate(
+                        getTemplate(EntityViolationType.InvalidValueList,
+                                "Invalid values " + object.getValuesAsStrings())).
+                        addPropertyNode(object.getSchema().getKey()).addConstraintViolation();
+            }
+        }
+
+        return isValid;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainAttrValueCheck.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainAttrValueCheck.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainAttrValueCheck.java
new file mode 100644
index 0000000..17cf362
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainAttrValueCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.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 = PlainAttrValueValidator.class)
+@Documented
+public @interface PlainAttrValueCheck {
+
+    String message() default "{org.apache.syncope.persistence.validation.attrvalue}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainAttrValueValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainAttrValueValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainAttrValueValidator.java
new file mode 100644
index 0000000..f68bb66
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainAttrValueValidator.java
@@ -0,0 +1,98 @@
+/*
+ * 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.persistence.jpa.validation.entity;
+
+import javax.validation.ConstraintValidatorContext;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.persistence.api.entity.PlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.apache.syncope.persistence.api.entity.membership.MPlainSchema;
+import org.apache.syncope.persistence.api.entity.role.RPlainSchema;
+import org.apache.syncope.persistence.api.entity.user.UPlainSchema;
+
+public class PlainAttrValueValidator extends AbstractValidator<PlainAttrValueCheck, PlainAttrValue> {
+
+    @Override
+    public boolean isValid(final PlainAttrValue object, final ConstraintValidatorContext context) {
+        boolean isValid;
+
+        if (object == null) {
+            isValid = true;
+        } else {
+            int nonNullVales = 0;
+            if (object.getBooleanValue() != null) {
+                nonNullVales++;
+            }
+            if (object.getDateValue() != null) {
+                nonNullVales++;
+            }
+            if (object.getDoubleValue() != null) {
+                nonNullVales++;
+            }
+            if (object.getLongValue() != null) {
+                nonNullVales++;
+            }
+            if (object.getBinaryValue() != null) {
+                nonNullVales++;
+            }
+            if (object.getStringValue() != null) {
+                nonNullVales++;
+            }
+            isValid = nonNullVales == 1;
+
+            if (!isValid) {
+                LOG.error("More than one non-null value for " + object);
+
+                context.disableDefaultConstraintViolation();
+                context.buildConstraintViolationWithTemplate(
+                        getTemplate(EntityViolationType.MoreThanOneNonNull, "More than one non-null value found")).
+                        addPropertyNode(object.getClass().getSimpleName().replaceAll("\\n", " ")).
+                        addConstraintViolation();
+
+            } else if (object instanceof PlainAttrUniqueValue) {
+                PlainSchema uniqueValueSchema = ((PlainAttrUniqueValue) object).getSchema();
+                PlainSchema attrSchema = object.getAttr().getSchema();
+
+                isValid = uniqueValueSchema.equals(attrSchema);
+
+                if (!isValid) {
+                    LOG.error("Unique value schema for " + object.getClass().getSimpleName() + "[" + object.getKey()
+                            + "]" + " is " + uniqueValueSchema + ", while owning attribute schema is " + attrSchema);
+
+                    EntityViolationType violationType = attrSchema instanceof UPlainSchema
+                            ? EntityViolationType.InvalidUPlainSchema
+                            : attrSchema instanceof RPlainSchema
+                                    ? EntityViolationType.InvalidRPlainSchema
+                                    : attrSchema instanceof MPlainSchema
+                                            ? EntityViolationType.InvalidMPlainSchema
+                                            : EntityViolationType.InvalidCPlainSchema;
+
+                    context.disableDefaultConstraintViolation();
+                    context.buildConstraintViolationWithTemplate(getTemplate(violationType,
+                            "Unique value schema is " + uniqueValueSchema
+                            + ", while owning attribute schema is " + attrSchema)).addPropertyNode("schema").
+                            addConstraintViolation();
+                }
+            }
+        }
+
+        return isValid;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainSchemaCheck.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainSchemaCheck.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainSchemaCheck.java
new file mode 100644
index 0000000..fd25842
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainSchemaCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.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 = PlainSchemaValidator.class)
+@Documented
+public @interface PlainSchemaCheck {
+
+    String message() default "{org.apache.syncope.persistence.validation.schema}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}


[15/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/spring/src/main/java/org/apache/syncope/server/spring/BeanUtils.java
----------------------------------------------------------------------
diff --git a/syncope620/server/spring/src/main/java/org/apache/syncope/server/spring/BeanUtils.java b/syncope620/server/spring/src/main/java/org/apache/syncope/server/spring/BeanUtils.java
new file mode 100644
index 0000000..f937b40
--- /dev/null
+++ b/syncope620/server/spring/src/main/java/org/apache/syncope/server/spring/BeanUtils.java
@@ -0,0 +1,201 @@
+/*
+ * 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.server.spring;
+
+import static org.springframework.beans.BeanUtils.getPropertyDescriptor;
+import static org.springframework.beans.BeanUtils.getPropertyDescriptors;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.FatalBeanException;
+import org.springframework.util.Assert;
+import org.springframework.util.ClassUtils;
+
+/**
+ * Overrides Spring's BeanUtils not using collection setters but instead getters + addAll() / putAll(),
+ * in a JAXB friendly way.
+ *
+ * Refer to <a href="https://issues.apache.org/jira/browse/SYNCOPE-246">SYNCOPE-246</a> for more information.
+ *
+ * @see org.springframework.beans.BeanUtils
+ */
+public final class BeanUtils {
+
+    private BeanUtils() {
+        // Empty private constructor for static utility classes
+    }
+
+    /**
+     * Copy the property values of the given source bean into the target bean.
+     * <p>
+     * Note: The source and target classes do not have to match or even be derived
+     * from each other, as long as the properties match. Any bean properties that the
+     * source bean exposes but the target bean does not will silently be ignored.
+     * </p><p>
+     * This is just a convenience method. For more complex transfer needs,
+     * consider using a full BeanWrapper.
+     * </p>
+     * @param source the source bean
+     * @param target the target bean
+     * @throws BeansException if the copying failed
+     * @see org.springframework.beans.BeanWrapper
+     */
+    public static void copyProperties(final Object source, final Object target) throws BeansException {
+        copyProperties(source, target, null, (String[]) null);
+    }
+
+    /**
+     * Copy the property values of the given source bean into the given target bean,
+     * only setting properties defined in the given "editable" class (or interface).
+     * <p>
+     * Note: The source and target classes do not have to match or even be derived
+     * from each other, as long as the properties match. Any bean properties that the
+     * source bean exposes but the target bean does not will silently be ignored.
+     * </p><p>
+     * This is just a convenience method. For more complex transfer needs,
+     * consider using a full BeanWrapper.
+     * </p>
+     *
+     * @param source the source bean
+     * @param target the target bean
+     * @param editable the class (or interface) to restrict property setting to
+     * @throws BeansException if the copying failed
+     * @see org.springframework.beans.BeanWrapper
+     */
+    public static void copyProperties(final Object source, final Object target, final Class<?> editable)
+            throws BeansException {
+
+        copyProperties(source, target, editable, (String[]) null);
+    }
+
+    /**
+     * Copy the property values of the given source bean into the given target bean,
+     * ignoring the given "ignoreProperties".
+     * <p>
+     * Note: The source and target classes do not have to match or even be derived
+     * from each other, as long as the properties match. Any bean properties that the
+     * source bean exposes but the target bean does not will silently be ignored.
+     * </p><p>
+     * This is just a convenience method. For more complex transfer needs,
+     * consider using a full BeanWrapper.
+     * </p>
+     *
+     * @param source the source bean
+     * @param target the target bean
+     * @param ignoreProperties array of property names to ignore
+     * @throws BeansException if the copying failed
+     * @see org.springframework.beans.BeanWrapper
+     */
+    public static void copyProperties(final Object source, final Object target, final String... ignoreProperties)
+            throws BeansException {
+
+        copyProperties(source, target, null, ignoreProperties);
+    }
+
+    /**
+     * Copy the property values of the given source bean into the given target bean.
+     * <p>
+     * Note: The source and target classes do not have to match or even be derived
+     * from each other, as long as the properties match. Any bean properties that the
+     * source bean exposes but the target bean does not will silently be ignored.
+     * </p>
+     *
+     * @param source the source bean
+     * @param target the target bean
+     * @param editable the class (or interface) to restrict property setting to
+     * @param ignoreProperties array of property names to ignore
+     * @throws BeansException if the copying failed
+     * @see org.springframework.beans.BeanWrapper
+     */
+    @SuppressWarnings("unchecked")
+    private static void copyProperties(final Object source, final Object target, final Class<?> editable,
+            final String... ignoreProperties) throws BeansException {
+
+        Assert.notNull(source, "Source must not be null");
+        Assert.notNull(target, "Target must not be null");
+
+        Class<?> actualEditable = target.getClass();
+        if (editable != null) {
+            if (!editable.isInstance(target)) {
+                throw new IllegalArgumentException("Target class [" + target.getClass().getName()
+                        + "] not assignable to Editable class [" + editable.getName() + "]");
+            }
+            actualEditable = editable;
+        }
+        PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
+        List<String> ignoreList = (ignoreProperties == null)
+                ? Collections.<String>emptyList() : Arrays.asList(ignoreProperties);
+
+        for (PropertyDescriptor targetPd : targetPds) {
+            if (ignoreProperties == null || (!ignoreList.contains(targetPd.getName()))) {
+                PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
+                if (sourcePd != null) {
+                    Method readMethod = sourcePd.getReadMethod();
+                    if (readMethod != null) {
+                        Method writeMethod = targetPd.getWriteMethod();
+
+                        try {
+                            // Diverts from Spring's BeanUtils: if no write method is found and property is collection,
+                            // try to use addAll() / putAll().
+                            if (writeMethod == null) {
+                                Object value = readMethod.invoke(source);
+                                Method targetReadMethod = targetPd.getReadMethod();
+                                if (targetReadMethod != null) {
+                                    if (!Modifier.isPublic(targetReadMethod.getDeclaringClass().getModifiers())) {
+                                        targetReadMethod.setAccessible(true);
+                                    }
+                                    Object destValue = targetReadMethod.invoke(target);
+
+                                    if (value instanceof Collection && destValue instanceof Collection) {
+                                        ((Collection) destValue).clear();
+                                        ((Collection) destValue).addAll((Collection) value);
+                                    } else if (value instanceof Map && destValue instanceof Map) {
+                                        ((Map) destValue).clear();
+                                        ((Map) destValue).putAll((Map) value);
+                                    }
+                                }
+                            } else if (ClassUtils.isAssignable(
+                                    writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
+
+                                if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
+                                    readMethod.setAccessible(true);
+                                }
+                                Object value = readMethod.invoke(source);
+                                if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
+                                    writeMethod.setAccessible(true);
+                                }
+                                writeMethod.invoke(target, value);
+                            }
+                        } catch (Throwable ex) {
+                            throw new FatalBeanException(
+                                    "Could not copy property '" + targetPd.getName() + "' from source to target", ex);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/spring/src/main/java/org/apache/syncope/server/spring/ResourceWithFallbackLoader.java
----------------------------------------------------------------------
diff --git a/syncope620/server/spring/src/main/java/org/apache/syncope/server/spring/ResourceWithFallbackLoader.java b/syncope620/server/spring/src/main/java/org/apache/syncope/server/spring/ResourceWithFallbackLoader.java
new file mode 100644
index 0000000..9b771b3
--- /dev/null
+++ b/syncope620/server/spring/src/main/java/org/apache/syncope/server/spring/ResourceWithFallbackLoader.java
@@ -0,0 +1,82 @@
+/*
+ * 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.server.spring;
+
+import java.io.IOException;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.ArrayUtils;
+import org.springframework.context.ResourceLoaderAware;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.core.io.support.ResourcePatternResolver;
+
+public class ResourceWithFallbackLoader implements ResourceLoaderAware, ResourcePatternResolver {
+
+    private ResourcePatternResolver resolver;
+
+    private String primary;
+
+    private String fallback;
+
+    @Override
+    public void setResourceLoader(final ResourceLoader resourceLoader) {
+        this.resolver = (ResourcePatternResolver) resourceLoader;
+    }
+
+    public void setPrimary(final String primary) {
+        this.primary = primary;
+    }
+
+    public void setFallback(final String fallback) {
+        this.fallback = fallback;
+    }
+
+    @Override
+    public Resource getResource(final String location) {
+        Resource resource = resolver.getResource(primary + location);
+        if (!resource.exists()) {
+            resource = resolver.getResource(fallback + location);
+        }
+
+        return resource;
+    }
+
+    public Resource getResource() {
+        return getResource(StringUtils.EMPTY);
+    }
+
+    @Override
+    public Resource[] getResources(final String locationPattern) throws IOException {
+        Resource[] resources = resolver.getResources(primary + locationPattern);
+        if (ArrayUtils.isEmpty(resources)) {
+            resources = resolver.getResources(fallback + locationPattern);
+        }
+
+        return resources;
+    }
+
+    public Resource[] getResources() throws IOException {
+        return getResources(StringUtils.EMPTY);
+    }
+
+    @Override
+    public ClassLoader getClassLoader() {
+        return resolver.getClassLoader();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/pom.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/pom.xml b/syncope620/server/utils/pom.xml
new file mode 100644
index 0000000..af4a55e
--- /dev/null
+++ b/syncope620/server/utils/pom.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.syncope</groupId>
+    <artifactId>syncope-server</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Server Utilities</name>
+  <description>Apache Syncope Server Utilities</description>
+  <groupId>org.apache.syncope.server</groupId>
+  <artifactId>syncope-server-utils</artifactId>
+  <packaging>jar</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-jexl</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.module</groupId>
+      <artifactId>jackson-module-afterburner</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.syncope.server</groupId>
+      <artifactId>syncope-persistence-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/DataFormat.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/DataFormat.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/DataFormat.java
new file mode 100644
index 0000000..d30f3c4
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/DataFormat.java
@@ -0,0 +1,117 @@
+/*
+ * 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.server.utils;
+
+import java.text.DecimalFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import org.apache.commons.lang3.time.DateUtils;
+import org.apache.syncope.common.lib.SyncopeConstants;
+
+/**
+ * Utility class for parsing / formatting date and numbers.
+ */
+public final class DataFormat {
+
+    private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT = new ThreadLocal<SimpleDateFormat>() {
+
+        @Override
+        protected SimpleDateFormat initialValue() {
+            SimpleDateFormat sdf = new SimpleDateFormat();
+            sdf.applyPattern(SyncopeConstants.DEFAULT_DATE_PATTERN);
+            return sdf;
+        }
+    };
+
+    private static final ThreadLocal<DecimalFormat> DECIMAL_FORMAT = new ThreadLocal<DecimalFormat>() {
+
+        @Override
+        protected DecimalFormat initialValue() {
+            return new DecimalFormat();
+        }
+    };
+
+    public static String format(final Date date) {
+        return format(date, true);
+    }
+
+    public static String format(final Date date, final boolean lenient) {
+        return format(date, lenient, null);
+    }
+
+    public static String format(final Date date, final boolean lenient, final String conversionPattern) {
+        SimpleDateFormat sdf = DATE_FORMAT.get();
+        if (conversionPattern != null) {
+            sdf.applyPattern(conversionPattern);
+        }
+        sdf.setLenient(lenient);
+        return sdf.format(date);
+    }
+
+    public static String format(final long number) {
+        return format(number, null);
+    }
+
+    public static String format(final long number, final String conversionPattern) {
+        DecimalFormat df = DECIMAL_FORMAT.get();
+        if (conversionPattern != null) {
+            df.applyPattern(conversionPattern);
+        }
+        return df.format(number);
+    }
+
+    public static String format(final double number) {
+        return format(number, null);
+    }
+
+    public static String format(final double number, final String conversionPattern) {
+        DecimalFormat df = DECIMAL_FORMAT.get();
+        if (conversionPattern != null) {
+            df.applyPattern(conversionPattern);
+        }
+        return df.format(number);
+    }
+
+    public static Date parseDate(final String source) throws ParseException {
+        return DateUtils.parseDate(source, SyncopeConstants.DATE_PATTERNS);
+    }
+
+    public static Date parseDate(final String source, final String conversionPattern) throws ParseException {
+        SimpleDateFormat sdf = DATE_FORMAT.get();
+        sdf.applyPattern(conversionPattern);
+        sdf.setLenient(false);
+        return sdf.parse(source);
+    }
+
+    public static Number parseNumber(final String source, final String conversionPattern) throws ParseException {
+        DecimalFormat df = DECIMAL_FORMAT.get();
+        df.applyPattern(conversionPattern);
+        return df.parse(source);
+    }
+
+    public static void clear() {
+        DATE_FORMAT.remove();
+        DECIMAL_FORMAT.remove();
+    }
+
+    private DataFormat() {
+        // private empty constructor
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/URIUtil.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/URIUtil.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/URIUtil.java
new file mode 100644
index 0000000..903b8ca
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/URIUtil.java
@@ -0,0 +1,61 @@
+/*
+ * 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.server.utils;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+public final class URIUtil {
+
+    private URIUtil() {
+        // empty constructor for static utility class
+    }
+
+    /**
+     * Build a valid URI out of the given location.
+     * Only "file", "connid" and "connids" schemes are allowed.
+     * For "file", invalid characters are handled via intermediate transformation into URL.
+     *
+     * @param location the candidate location for URI
+     * @return valid URI for the given location
+     * @throws MalformedURLException if the intermediate URL is not valid
+     * @throws URISyntaxException if the given location does not correspond to a valid URI
+     */
+    public static URI buildForConnId(final String location) throws MalformedURLException, URISyntaxException {
+        final String candidate = location.trim();
+
+        if (!candidate.startsWith("file:")
+                && !candidate.startsWith("connid:") && !candidate.startsWith("connids:")) {
+
+            throw new IllegalArgumentException(candidate + " is not a valid URI for file or connid(s) schemes");
+        }
+
+        URI uri;
+        if (candidate.startsWith("file:")) {
+            uri = new File(new URL(candidate).getFile()).getAbsoluteFile().toURI();
+        } else {
+            uri = new URI(candidate);
+        }
+
+        return uri;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/jexl/ClassFreeUberspectImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/jexl/ClassFreeUberspectImpl.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/jexl/ClassFreeUberspectImpl.java
new file mode 100644
index 0000000..15d06dd
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/jexl/ClassFreeUberspectImpl.java
@@ -0,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.server.utils.jexl;
+
+import org.apache.commons.jexl2.JexlInfo;
+import org.apache.commons.jexl2.introspection.JexlMethod;
+import org.apache.commons.jexl2.introspection.JexlPropertyGet;
+import org.apache.commons.jexl2.introspection.UberspectImpl;
+import org.apache.commons.logging.Log;
+
+class ClassFreeUberspectImpl extends UberspectImpl {
+
+    public ClassFreeUberspectImpl(final Log runtimeLogger) {
+        super(runtimeLogger);
+    }
+
+    @Override
+    public JexlPropertyGet getPropertyGet(final Object obj, final Object identifier, final JexlInfo info) {
+        return "class".equals(identifier) ? null : super.getPropertyGet(obj, identifier, info);
+    }
+
+    @Override
+    public JexlMethod getMethod(final Object obj, final String method, final Object[] args, final JexlInfo info) {
+        return "getClass".equals(method) ? null : super.getMethod(obj, method, args, info);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/jexl/EmptyClassLoader.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/jexl/EmptyClassLoader.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/jexl/EmptyClassLoader.java
new file mode 100644
index 0000000..4564aad
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/jexl/EmptyClassLoader.java
@@ -0,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.server.utils.jexl;
+
+/**
+ * A class loader that will throw {@link ClassNotFoundException} for every class name.
+ */
+class EmptyClassLoader extends ClassLoader {
+
+    @Override
+    public Class<?> loadClass(final String name) throws ClassNotFoundException {
+        throw new ClassNotFoundException("This classloader won't attemp to load " + name);
+    }
+
+    @Override
+    protected Class<?> loadClass(final String name, boolean resolve) throws ClassNotFoundException {
+        throw new ClassNotFoundException("This classloader won't attemp to load " + name);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/jexl/JexlUtil.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/jexl/JexlUtil.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/jexl/JexlUtil.java
new file mode 100644
index 0000000..d160ef4
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/jexl/JexlUtil.java
@@ -0,0 +1,289 @@
+/*
+ * 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.server.utils.jexl;
+
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import org.apache.commons.jexl2.Expression;
+import org.apache.commons.jexl2.JexlContext;
+import org.apache.commons.jexl2.JexlEngine;
+import org.apache.commons.jexl2.JexlException;
+import org.apache.commons.jexl2.MapContext;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.persistence.api.entity.Attributable;
+import org.apache.syncope.persistence.api.entity.DerAttr;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.VirAttr;
+import org.apache.syncope.server.utils.DataFormat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * JEXL <a href="http://commons.apache.org/jexl/reference/index.html">reference</a> is available.
+ */
+public final class JexlUtil {
+
+    /**
+     * Logger.
+     *
+     */
+    private static final Logger LOG = LoggerFactory.getLogger(JexlUtil.class);
+
+    private static final String[] IGNORE_FIELDS = { "password", "clearPassword", "serialVersionUID", "class" };
+
+    private static JexlEngine jexlEngine;
+
+    private static JexlEngine getEngine() {
+        synchronized (LOG) {
+            if (jexlEngine == null) {
+                jexlEngine = new JexlEngine(new ClassFreeUberspectImpl(null), null, null, null);
+                jexlEngine.setClassLoader(new EmptyClassLoader());
+                jexlEngine.setCache(512);
+                jexlEngine.setLenient(true);
+                jexlEngine.setSilent(false);
+            }
+        }
+
+        return jexlEngine;
+    }
+
+    public static boolean isExpressionValid(final String expression) {
+        boolean result;
+        try {
+            getEngine().createExpression(expression);
+            result = true;
+        } catch (JexlException e) {
+            LOG.error("Invalid jexl expression: " + expression, e);
+            result = false;
+        }
+
+        return result;
+    }
+
+    public static String evaluate(final String expression, final JexlContext jexlContext) {
+        String result = StringUtils.EMPTY;
+
+        if (StringUtils.isNotBlank(expression) && jexlContext != null) {
+            try {
+                Expression jexlExpression = getEngine().createExpression(expression);
+                Object evaluated = jexlExpression.evaluate(jexlContext);
+                if (evaluated != null) {
+                    result = evaluated.toString();
+                }
+            } catch (Exception e) {
+                LOG.error("Error while evaluating JEXL expression: " + expression, e);
+            }
+        } else {
+            LOG.debug("Expression not provided or invalid context");
+        }
+
+        return result;
+    }
+
+    public static JexlContext addFieldsToContext(final Object object, final JexlContext jexlContext) {
+        JexlContext context = jexlContext == null ? new MapContext() : jexlContext;
+
+        try {
+            for (PropertyDescriptor desc : Introspector.getBeanInfo(object.getClass()).getPropertyDescriptors()) {
+                final Class<?> type = desc.getPropertyType();
+                final String fieldName = desc.getName();
+
+                if ((!fieldName.startsWith("pc"))
+                        && (!ArrayUtils.contains(IGNORE_FIELDS, fieldName))
+                        && (!Iterable.class.isAssignableFrom(type))
+                        && (!type.isArray())) {
+                    try {
+                        final Method getter = desc.getReadMethod();
+
+                        final Object fieldValue;
+
+                        if (getter == null) {
+                            final Field field = object.getClass().getDeclaredField(fieldName);
+                            field.setAccessible(true);
+                            fieldValue = field.get(object);
+                        } else {
+                            fieldValue = getter.invoke(object);
+                        }
+
+                        context.set(fieldName, fieldValue == null
+                                ? StringUtils.EMPTY
+                                : (type.equals(Date.class)
+                                        ? DataFormat.format((Date) fieldValue, false)
+                                        : fieldValue));
+
+                        LOG.debug("Add field {} with value {}", fieldName, fieldValue);
+
+                    } catch (Exception iae) {
+                        LOG.error("Reading '{}' value error", fieldName, iae);
+                    }
+                }
+            }
+        } catch (IntrospectionException ie) {
+            LOG.error("Reading class attributes error", ie);
+        }
+
+        return context;
+    }
+
+    public static JexlContext addAttrsToContext(final Collection<? extends PlainAttr> attrs,
+            final JexlContext jexlContext) {
+
+        JexlContext context = jexlContext == null
+                ? new MapContext()
+                : jexlContext;
+
+        for (PlainAttr attr : attrs) {
+            if (attr.getSchema() != null) {
+                List<String> attrValues = attr.getValuesAsStrings();
+                String expressionValue = attrValues.isEmpty()
+                        ? StringUtils.EMPTY
+                        : attrValues.get(0);
+
+                LOG.debug("Add attribute {} with value {}", attr.getSchema().getKey(), expressionValue);
+
+                context.set(attr.getSchema().getKey(), expressionValue);
+            }
+        }
+
+        return context;
+    }
+
+    public static JexlContext addDerAttrsToContext(final Collection<? extends DerAttr> derAttrs,
+            final Collection<? extends PlainAttr> attrs, final JexlContext jexlContext) {
+
+        JexlContext context = jexlContext == null
+                ? new MapContext()
+                : jexlContext;
+
+        for (DerAttr derAttr : derAttrs) {
+            if (derAttr.getSchema() != null) {
+                String expressionValue = derAttr.getValue(attrs);
+                if (expressionValue == null) {
+                    expressionValue = StringUtils.EMPTY;
+                }
+
+                LOG.debug("Add derived attribute {} with value {}", derAttr.getSchema().getKey(), expressionValue);
+
+                context.set(derAttr.getSchema().getKey(), expressionValue);
+            }
+        }
+
+        return context;
+    }
+
+    public static JexlContext addVirAttrsToContext(final Collection<? extends VirAttr> virAttrs,
+            final JexlContext jexlContext) {
+
+        JexlContext context = jexlContext == null
+                ? new MapContext()
+                : jexlContext;
+
+        for (VirAttr virAttr : virAttrs) {
+            if (virAttr.getSchema() != null) {
+                List<String> attrValues = virAttr.getValues();
+                String expressionValue = attrValues.isEmpty()
+                        ? StringUtils.EMPTY
+                        : attrValues.get(0);
+
+                LOG.debug("Add virtual attribute {} with value {}", virAttr.getSchema().getKey(), expressionValue);
+
+                context.set(virAttr.getSchema().getKey(), expressionValue);
+            }
+        }
+
+        return context;
+    }
+
+    public static boolean evaluateMandatoryCondition(
+            final String mandatoryCondition, final Attributable<?, ?, ?> attributable) {
+
+        JexlContext jexlContext = new MapContext();
+        addAttrsToContext(attributable.getPlainAttrs(), jexlContext);
+        addDerAttrsToContext(attributable.getDerAttrs(), attributable.getPlainAttrs(), jexlContext);
+        addVirAttrsToContext(attributable.getVirAttrs(), jexlContext);
+
+        return Boolean.parseBoolean(evaluate(mandatoryCondition, jexlContext));
+    }
+
+    public static String evaluate(final String expression,
+            final Attributable<?, ?, ?> attributable, final Collection<? extends PlainAttr> attributes) {
+
+        final JexlContext jexlContext = new MapContext();
+        JexlUtil.addAttrsToContext(attributes, jexlContext);
+        JexlUtil.addFieldsToContext(attributable, jexlContext);
+
+        // Evaluate expression using the context prepared before
+        return evaluate(expression, jexlContext);
+    }
+
+    public static String evaluate(final String expression, final AbstractAttributableTO attributableTO) {
+        final JexlContext context = new MapContext();
+
+        addFieldsToContext(attributableTO, context);
+
+        for (AttrTO plainAttr : attributableTO.getPlainAttrs()) {
+            List<String> values = plainAttr.getValues();
+            String expressionValue = values.isEmpty()
+                    ? StringUtils.EMPTY
+                    : values.get(0);
+
+            LOG.debug("Add plain attribute {} with value {}", plainAttr.getSchema(), expressionValue);
+
+            context.set(plainAttr.getSchema(), expressionValue);
+        }
+        for (AttrTO derAttr : attributableTO.getDerAttrs()) {
+            List<String> values = derAttr.getValues();
+            String expressionValue = values.isEmpty()
+                    ? StringUtils.EMPTY
+                    : values.get(0);
+
+            LOG.debug("Add derived attribute {} with value {}", derAttr.getSchema(), expressionValue);
+
+            context.set(derAttr.getSchema(), expressionValue);
+        }
+        for (AttrTO virAttr : attributableTO.getVirAttrs()) {
+            List<String> values = virAttr.getValues();
+            String expressionValue = values.isEmpty()
+                    ? StringUtils.EMPTY
+                    : values.get(0);
+
+            LOG.debug("Add virtual attribute {} with value {}", virAttr.getSchema(), expressionValue);
+
+            context.set(virAttr.getSchema(), expressionValue);
+        }
+
+        // Evaluate expression using the context prepared before
+        return evaluate(expression, context);
+    }
+
+    /**
+     * Private default constructor, for static-only classes.
+     */
+    private JexlUtil() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/AccountPolicyEnforcer.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/AccountPolicyEnforcer.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/AccountPolicyEnforcer.java
new file mode 100644
index 0000000..0a4bdd3
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/AccountPolicyEnforcer.java
@@ -0,0 +1,101 @@
+/*
+ * 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.server.utils.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.persistence.api.entity.user.User;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AccountPolicyEnforcer implements PolicyEnforcer<AccountPolicySpec, User> {
+
+    private static final Pattern DEFAULT_PATTERN = Pattern.compile("[a-zA-Z0-9-_@. ]+");
+
+    @Autowired(required = false)
+    private UserSuspender userSuspender;
+
+    @Override
+    public void enforce(final AccountPolicySpec policy, final PolicyType type, final User user)
+            throws AccountPolicyException, PolicyEnforceException {
+
+        if (user.getUsername() == null) {
+            throw new PolicyEnforceException("Invalid account");
+        }
+
+        if (policy == null) {
+            throw new PolicyEnforceException("Invalid policy");
+        }
+
+        // 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
+        if (userSuspender != null
+                && user.getFailedLogins() != null && policy.getPermittedLoginRetries() > 0
+                && user.getFailedLogins() > policy.getPermittedLoginRetries() && !user.isSuspended()) {
+
+            userSuspender.suspend(user, policy.isPropagateSuspension());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/AccountPolicyException.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/AccountPolicyException.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/AccountPolicyException.java
new file mode 100644
index 0000000..7173f0e
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/AccountPolicyException.java
@@ -0,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.server.utils.policy;
+
+public class AccountPolicyException extends PolicyException {
+
+    private static final long serialVersionUID = 2779416455067691813L;
+
+    public AccountPolicyException() {
+        super();
+    }
+
+    public AccountPolicyException(final String message) {
+        super(message);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PasswordPolicyEnforcer.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PasswordPolicyEnforcer.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PasswordPolicyEnforcer.java
new file mode 100644
index 0000000..ff0a3f6
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PasswordPolicyEnforcer.java
@@ -0,0 +1,202 @@
+/*
+ * 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.server.utils.policy;
+
+import org.apache.syncope.common.lib.types.PasswordPolicySpec;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.springframework.stereotype.Component;
+
+@Component
+public class PasswordPolicyEnforcer implements PolicyEnforcer<PasswordPolicySpec, User> {
+
+    /* (non-Javadoc)
+     * @see
+     * org.apache.syncope.core.policy.PasswordPolicyEnforcer#enforce(org.apache.syncope.common.types.PasswordPolicySpec,
+     * org.apache.syncope.common.types.PolicyType, java.lang.String)
+     */
+    @Override
+    public void enforce(final PasswordPolicySpec policy, final PolicyType type, final User user)
+            throws PasswordPolicyException, PolicyEnforceException {
+
+        final String clearPassword = user.getClearPassword();
+        final String password = user.getPassword();
+
+        if (policy == null) {
+            throw new PolicyEnforceException("Invalid policy");
+        }
+
+        if (password == null && !policy.isAllowNullPassword()) {
+            throw new PolicyEnforceException("Password must not be null and must be stored internally");
+        } else 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");
+            }
+        }
+    }
+
+    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/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PasswordPolicyException.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PasswordPolicyException.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PasswordPolicyException.java
new file mode 100644
index 0000000..866e8ff
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PasswordPolicyException.java
@@ -0,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.server.utils.policy;
+
+public class PasswordPolicyException extends PolicyException {
+
+    private static final long serialVersionUID = 8072104484395278469L;
+
+    public PasswordPolicyException() {
+        super();
+    }
+
+    public PasswordPolicyException(final String message) {
+        super(message);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyEnforceException.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyEnforceException.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyEnforceException.java
new file mode 100644
index 0000000..c4d2aac
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyEnforceException.java
@@ -0,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.server.utils.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/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyEnforcer.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyEnforcer.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyEnforcer.java
new file mode 100644
index 0000000..b057773
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyEnforcer.java
@@ -0,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.server.utils.policy;
+
+import java.io.InvalidObjectException;
+
+import org.apache.syncope.common.lib.types.PolicySpec;
+import org.apache.syncope.common.lib.types.PolicyType;
+
+public interface PolicyEnforcer<T extends PolicySpec, E> {
+
+    void enforce(final T policy, final PolicyType type, final E object)
+            throws InvalidObjectException, PolicyException;
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyEvaluator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyEvaluator.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyEvaluator.java
new file mode 100644
index 0000000..58b31b2
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyEvaluator.java
@@ -0,0 +1,109 @@
+/*
+ * 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.server.utils.policy;
+
+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.persistence.api.entity.Attributable;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.Policy;
+import org.apache.syncope.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 {
+
+    /**
+     * Logger.
+     */
+    private static final Logger LOG = LoggerFactory.getLogger(PolicyEvaluator.class);
+
+    @SuppressWarnings("unchecked")
+    public <T extends PolicySpec> T evaluate(final Policy policy, final Attributable<?, ?, ?> attributable) {
+        if (policy == null) {
+            return null;
+        }
+
+        T result = null;
+        switch (policy.getType()) {
+            case PASSWORD:
+            case GLOBAL_PASSWORD:
+                final PasswordPolicySpec ppSpec = policy.getSpecification(PasswordPolicySpec.class);
+                final PasswordPolicySpec evaluatedPPSpec = new PasswordPolicySpec();
+
+                BeanUtils.copyProperties(ppSpec, evaluatedPPSpec, new String[] { "schemasNotPermitted" });
+
+                for (String schema : ppSpec.getSchemasNotPermitted()) {
+                    PlainAttr attr = attributable.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 (!(attributable instanceof User)) {
+                    LOG.error("Cannot check previous passwords. attributable is not a user object: {}",
+                            attributable.getClass().getName());
+                    result = (T) evaluatedPPSpec;
+                    break;
+                }
+                User user = (User) attributable;
+                if (user.verifyPasswordHistory(user.getClearPassword(), ppSpec.getHistoryLength())) {
+                    evaluatedPPSpec.getWordsNotPermitted().add(user.getClearPassword());
+                }
+                result = (T) evaluatedPPSpec;
+                break;
+
+            case ACCOUNT:
+            case GLOBAL_ACCOUNT:
+                final AccountPolicySpec spec = policy.getSpecification(AccountPolicySpec.class);
+                final AccountPolicySpec accountPolicy = new AccountPolicySpec();
+
+                BeanUtils.copyProperties(spec, accountPolicy, new String[] { "schemasNotPermitted" });
+
+                for (String schema : spec.getSchemasNotPermitted()) {
+                    PlainAttr attr = attributable.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;
+
+            case SYNC:
+            case GLOBAL_SYNC:
+            default:
+                result = null;
+        }
+
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyException.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyException.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyException.java
new file mode 100644
index 0000000..622d2f0
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyException.java
@@ -0,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.server.utils.policy;
+
+public class PolicyException extends RuntimeException {
+
+    private static final long serialVersionUID = -6082115004491662910L;
+
+    public PolicyException() {
+        super();
+    }
+
+    public PolicyException(final String message) {
+        super(message);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyPattern.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyPattern.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyPattern.java
new file mode 100644
index 0000000..9089995
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/PolicyPattern.java
@@ -0,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.server.utils.policy;
+
+import java.util.regex.Pattern;
+
+public final class PolicyPattern {
+
+    public static final Pattern DIGIT = Pattern.compile(".*\\d+.*");
+
+    public static final Pattern ALPHA_LOWERCASE = Pattern.compile(".*[a-z]+.*");
+
+    public static final Pattern ALPHA_UPPERCASE = Pattern.compile(".*[A-Z]+.*");
+
+    public static final Pattern FIRST_DIGIT = Pattern.compile("\\d.*");
+
+    public static final Pattern LAST_DIGIT = Pattern.compile(".*\\d");
+
+    public static final Pattern ALPHANUMERIC = Pattern.compile(".*\\w.*");
+
+    public static final Pattern FIRST_ALPHANUMERIC = Pattern.compile("\\w.*");
+
+    public static final Pattern LAST_ALPHANUMERIC = Pattern.compile(".*\\w");
+
+    public static final Pattern NON_ALPHANUMERIC = Pattern.compile(".*\\W.*");
+
+    public static final Pattern FIRST_NON_ALPHANUMERIC = Pattern.compile("\\W.*");
+
+    public static final Pattern LAST_NON_ALPHANUMERIC = Pattern.compile(".*\\W");
+
+    private PolicyPattern() {
+        // private constructor for static utility class
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/UserSuspender.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/UserSuspender.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/UserSuspender.java
new file mode 100644
index 0000000..3b4da6a
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/policy/UserSuspender.java
@@ -0,0 +1,26 @@
+/*
+ * 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.server.utils.policy;
+
+import org.apache.syncope.persistence.api.entity.user.User;
+
+public interface UserSuspender {
+
+    void suspend(User user, boolean propagateSuspension);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/AttributeDeserializer.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/AttributeDeserializer.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/AttributeDeserializer.java
new file mode 100644
index 0000000..b1a3790
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/AttributeDeserializer.java
@@ -0,0 +1,84 @@
+/*
+ * 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.server.utils.serialization;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.identityconnectors.common.Base64;
+import org.identityconnectors.common.security.GuardedString;
+import org.identityconnectors.framework.common.objects.Attribute;
+import org.identityconnectors.framework.common.objects.AttributeBuilder;
+import org.identityconnectors.framework.common.objects.Name;
+import org.identityconnectors.framework.common.objects.Uid;
+
+class AttributeDeserializer extends JsonDeserializer<Attribute> {
+
+    @Override
+    public Attribute deserialize(final JsonParser jp, final DeserializationContext ctx)
+            throws IOException, JsonProcessingException {
+
+        ObjectNode tree = jp.readValueAsTree();
+
+        String name = tree.get("name").asText();
+
+        List<Object> values = new ArrayList<Object>();
+        for (Iterator<JsonNode> itor = tree.get("value").iterator(); itor.hasNext();) {
+            JsonNode node = itor.next();
+            if (node.isNull()) {
+                values.add(null);
+            } else if (node.isObject()) {
+                values.add(((ObjectNode) node).traverse(jp.getCodec()).readValueAs(GuardedString.class));
+            } else if (node.isBoolean()) {
+                values.add(node.asBoolean());
+            } else if (node.isDouble()) {
+                values.add(node.asDouble());
+            } else if (node.isLong()) {
+                values.add(node.asLong());
+            } else if (node.isInt()) {
+                values.add(node.asInt());
+            } else {
+                String text = node.asText();
+                if (text.startsWith(AttributeSerializer.BYTE_ARRAY_PREFIX)
+                        && text.endsWith(AttributeSerializer.BYTE_ARRAY_SUFFIX)) {
+
+                    values.add(Base64.decode(StringUtils.substringBetween(
+                            text, AttributeSerializer.BYTE_ARRAY_PREFIX, AttributeSerializer.BYTE_ARRAY_SUFFIX)));
+                } else {
+                    values.add(text);
+                }
+            }
+        }
+
+        return Uid.NAME.equals(name)
+                ? new Uid(values.isEmpty() || values.get(0) == null ? null : values.get(0).toString())
+                : Name.NAME.equals(name)
+                ? new Name(values.isEmpty() || values.get(0) == null ? null : values.get(0).toString())
+                : AttributeBuilder.build(name, values);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/AttributeSerializer.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/AttributeSerializer.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/AttributeSerializer.java
new file mode 100644
index 0000000..2a75eec
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/AttributeSerializer.java
@@ -0,0 +1,78 @@
+/*
+ * 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.server.utils.serialization;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import java.io.IOException;
+import org.identityconnectors.common.Base64;
+import org.identityconnectors.common.security.GuardedString;
+import org.identityconnectors.framework.common.objects.Attribute;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class AttributeSerializer extends JsonSerializer<Attribute> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AttributeSerializer.class);
+
+    public static final String BYTE_ARRAY_PREFIX = "<binary>";
+
+    public static final String BYTE_ARRAY_SUFFIX = "</binary>";
+
+    @Override
+    public void serialize(final Attribute source, final JsonGenerator jgen, final SerializerProvider sp)
+            throws IOException, JsonProcessingException {
+
+        jgen.writeStartObject();
+
+        jgen.writeStringField("name", source.getName());
+
+        jgen.writeFieldName("value");
+        if (source.getValue() == null) {
+            jgen.writeNull();
+        } else {
+            jgen.writeStartArray();
+            for (Object value : source.getValue()) {
+                if (value == null) {
+                    jgen.writeNull();
+                } else if (value instanceof GuardedString) {
+                    jgen.writeObject(value);
+                } else if (value instanceof Integer) {
+                    jgen.writeNumber((Integer) value);
+                } else if (value instanceof Long) {
+                    jgen.writeNumber((Long) value);
+                } else if (value instanceof Double) {
+                    jgen.writeNumber((Double) value);
+                } else if (value instanceof Boolean) {
+                    jgen.writeBoolean((Boolean) value);
+                } else if (value instanceof byte[]) {
+                    jgen.writeString(BYTE_ARRAY_PREFIX + Base64.encode((byte[]) value) + BYTE_ARRAY_SUFFIX);
+                } else {
+                    jgen.writeString(value.toString());
+                }
+            }
+            jgen.writeEndArray();
+        }
+
+        jgen.writeEndObject();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/GuardedStringDeserializer.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/GuardedStringDeserializer.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/GuardedStringDeserializer.java
new file mode 100644
index 0000000..c05c94a
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/GuardedStringDeserializer.java
@@ -0,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.server.utils.serialization;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import org.identityconnectors.common.Base64;
+import org.identityconnectors.common.security.EncryptorFactory;
+import org.identityconnectors.common.security.GuardedString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class GuardedStringDeserializer extends JsonDeserializer<GuardedString> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(GuardedStringDeserializer.class);
+
+    @Override
+    public GuardedString deserialize(final JsonParser jp, final DeserializationContext ctx)
+            throws IOException, JsonProcessingException {
+
+        ObjectNode tree = jp.readValueAsTree();
+
+        boolean readOnly = false;
+        if (tree.has("readOnly")) {
+            readOnly = tree.get("readOnly").asBoolean();
+        }
+        boolean disposed = false;
+        if (tree.has("disposed")) {
+            disposed = tree.get("disposed").asBoolean();
+        }
+        byte[] encryptedBytes = null;
+        if (tree.has("encryptedBytes")) {
+            encryptedBytes = Base64.decode(tree.get("encryptedBytes").asText());
+        }
+        String base64SHA1Hash = null;
+        if (tree.has("base64SHA1Hash")) {
+            base64SHA1Hash = tree.get("base64SHA1Hash").asText();
+        }
+
+        final byte[] clearBytes = EncryptorFactory.getInstance().getDefaultEncryptor().decrypt(encryptedBytes);
+
+        GuardedString dest = new GuardedString(new String(clearBytes).toCharArray());
+
+        try {
+            Field field = GuardedString.class.getDeclaredField("readOnly");
+            field.setAccessible(true);
+            field.setBoolean(dest, readOnly);
+        } catch (Exception e) {
+            LOG.error("Could not set field value to {}", readOnly, e);
+        }
+
+        try {
+            Field field = GuardedString.class.getDeclaredField("disposed");
+            field.setAccessible(true);
+            field.setBoolean(dest, disposed);
+        } catch (Exception e) {
+            LOG.error("Could not set field value to {}", disposed, e);
+        }
+
+        if (base64SHA1Hash != null) {
+            try {
+                Field field = GuardedString.class.getDeclaredField("base64SHA1Hash");
+                field.setAccessible(true);
+                field.set(dest, base64SHA1Hash);
+            } catch (Exception e) {
+                LOG.error("Could not set field value to {}", base64SHA1Hash, e);
+            }
+        }
+
+        return dest;
+    }
+
+}


[02/32] syncope git commit: Merge branch '1_2_X' of https://git-wip-us.apache.org/repos/asf/syncope into 1_2_X

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


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

Branch: refs/heads/2_0_X
Commit: 4a2e843621464d7cce3ccda3cc76eb00b1c4f270
Parents: 3629cc1 7c0a5ef
Author: Marco Di Sabatino Di Diodoro <md...@apache.org>
Authored: Mon Dec 22 15:40:43 2014 +0100
Committer: Marco Di Sabatino Di Diodoro <md...@apache.org>
Committed: Mon Dec 22 15:40:43 2014 +0100

----------------------------------------------------------------------
 .../core/cache/DisabledVirAttrCache.java        |  50 +++++++
 .../syncope/core/cache/MemoryVirAttrCache.java  | 148 +++++++++++++++++++
 .../apache/syncope/core/cache/VirAttrCache.java |  65 ++++++++
 .../syncope/core/cache/VirAttrCacheKey.java     |  79 ++++++++++
 .../syncope/core/cache/VirAttrCacheValue.java   |  86 +++++++++++
 .../syncope/core/connid/ConnObjectUtil.java     |   4 +-
 .../data/AbstractAttributableDataBinder.java    |   2 +-
 .../apache/syncope/core/util/MappingUtil.java   |   7 +-
 .../apache/syncope/core/util/VirAttrCache.java  | 144 ------------------
 .../syncope/core/util/VirAttrCacheKey.java      |  79 ----------
 .../syncope/core/util/VirAttrCacheValue.java    |  86 -----------
 .../apache/syncope/core/util/jexl/JexlUtil.java |   4 +-
 core/src/main/resources/coreContext.xml         |   2 +-
 .../core/rest/DerivedSchemaTestITCase.java      |   4 +-
 14 files changed, 439 insertions(+), 321 deletions(-)
----------------------------------------------------------------------



[06/32] syncope git commit: Minor improvement

Posted by il...@apache.org.
Minor improvement


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

Branch: refs/heads/2_0_X
Commit: 553f10b64eac7a1789d550f522bfe2e638b75d88
Parents: 62faf63
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Fri Dec 26 09:19:00 2014 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Fri Dec 26 09:19:00 2014 +0100

----------------------------------------------------------------------
 .../org/apache/syncope/core/connid/ConnObjectUtil.java   |  5 +++--
 .../org/apache/syncope/core/util/AttributableUtil.java   | 11 ++++++++---
 2 files changed, 11 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/553f10b6/core/src/main/java/org/apache/syncope/core/connid/ConnObjectUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/syncope/core/connid/ConnObjectUtil.java b/core/src/main/java/org/apache/syncope/core/connid/ConnObjectUtil.java
index 814e83b..eaffe51 100644
--- a/core/src/main/java/org/apache/syncope/core/connid/ConnObjectUtil.java
+++ b/core/src/main/java/org/apache/syncope/core/connid/ConnObjectUtil.java
@@ -256,8 +256,9 @@ public class ConnObjectUtil {
         final T subjectTO = attrUtil.newSubjectTO();
 
         // 1. fill with data from connector object
-        for (AbstractMappingItem item : attrUtil.getUidToMappingItems(syncTask.getResource(),
-                MappingPurpose.SYNCHRONIZATION, attrUtil.getType())) {
+        for (AbstractMappingItem item : attrUtil.getUidToMappingItems(
+                syncTask.getResource(), MappingPurpose.SYNCHRONIZATION)) {
+
             Attribute attribute = obj.getAttributeByName(item.getExtAttrName());
 
             AttributeTO attributeTO;

http://git-wip-us.apache.org/repos/asf/syncope/blob/553f10b6/core/src/main/java/org/apache/syncope/core/util/AttributableUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/syncope/core/util/AttributableUtil.java b/core/src/main/java/org/apache/syncope/core/util/AttributableUtil.java
index b0e3830..354bed5 100644
--- a/core/src/main/java/org/apache/syncope/core/util/AttributableUtil.java
+++ b/core/src/main/java/org/apache/syncope/core/util/AttributableUtil.java
@@ -164,6 +164,7 @@ public final class AttributableUtil {
 
             case CONFIGURATION:
                 result = SyncopeConf.class;
+                break;
 
             case USER:
             default:
@@ -293,13 +294,16 @@ public final class AttributableUtil {
 
     @SuppressWarnings("unchecked")
     public <T extends AbstractMappingItem> List<T> getUidToMappingItems(
-            final ExternalResource resource, final MappingPurpose purpose, final AttributableType type) {
-        final List<T> items = getMappingItems(resource, MappingPurpose.SYNCHRONIZATION);
-        final AbstractMappingItem uidItem = type == AttributableType.USER ? new UMappingItem() : new RMappingItem();
+            final ExternalResource resource, final MappingPurpose purpose) {
+
+        List<T> items = getMappingItems(resource, purpose);
+
+        AbstractMappingItem uidItem = type == AttributableType.USER ? new UMappingItem() : new RMappingItem();
         BeanUtils.copyProperties(getAccountIdItem(resource), uidItem);
         uidItem.setExtAttrName(Uid.NAME);
         uidItem.setAccountid(false);
         items.add((T) uidItem);
+
         return items;
     }
 
@@ -315,6 +319,7 @@ public final class AttributableUtil {
                 break;
             case MEMBERSHIP:
                 result = AbstractMappingItem.class;
+                break;
             case CONFIGURATION:
             default:
         }


[10/32] syncope git commit: Upgrading Spring

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


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

Branch: refs/heads/2_0_X
Commit: 4b71b2c4480d3ad340a85441a0fc9a233a7f3ab8
Parents: bd10282
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu Jan 1 12:34:25 2015 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Jan 1 12:34:25 2015 +0100

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


http://git-wip-us.apache.org/repos/asf/syncope/blob/4b71b2c4/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 192048a..e4565ec 100644
--- a/pom.xml
+++ b/pom.xml
@@ -321,7 +321,7 @@ under the License.
     <activiti.version>5.15.1</activiti.version>
 
     <cxf.version>2.7.14</cxf.version>	
-    <spring.version>3.2.12.RELEASE</spring.version>
+    <spring.version>3.2.13.RELEASE</spring.version>
     <spring-security.version>3.1.7.RELEASE</spring-security.version>
     <aspectj.version>1.7.4</aspectj.version>
     <jackson.version>1.9.13</jackson.version>


[18/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/ResourceTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/ResourceTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/ResourceTest.java
new file mode 100644
index 0000000..bc51e2c
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/ResourceTest.java
@@ -0,0 +1,268 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.dao.ExternalResourceDAO;
+import org.apache.syncope.persistence.api.entity.ConnInstance;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.user.UMapping;
+import org.apache.syncope.persistence.api.entity.user.UMappingItem;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUMapping;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUMappingItem;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class ResourceTest extends AbstractTest {
+
+    @Autowired
+    private ExternalResourceDAO resourceDAO;
+
+    @Test
+    public void findById() {
+        ExternalResource resource = resourceDAO.find("ws-target-resource-1");
+        assertNotNull("findById did not work", resource);
+
+        ConnInstance connector = resource.getConnector();
+        assertNotNull("connector not found", connector);
+        assertEquals("invalid connector name",
+                "net.tirasa.connid.bundles.soap.WebServiceConnector", connector.getConnectorName());
+        assertEquals("invalid bundle name", "net.tirasa.connid.bundles.soap", connector.getBundleName());
+
+        assertFalse("no mapping specified", resource.getUmapping().getItems().isEmpty());
+
+        List<Long> mappingIds = new ArrayList<>();
+        for (UMappingItem item : resource.getUmapping().getItems()) {
+            mappingIds.add(item.getKey());
+        }
+        assertTrue(mappingIds.contains(100L));
+    }
+
+    @Test
+    public void findAll() {
+        List<ExternalResource> resources = resourceDAO.findAll();
+        assertNotNull(resources);
+        assertEquals(18, resources.size());
+    }
+
+    @Test
+    public void findAllByPriority() {
+        List<ExternalResource> resources = resourceDAO.findAllByPriority();
+        assertNotNull(resources);
+        assertFalse(resources.isEmpty());
+    }
+
+    @Test
+    public void getAccountId() {
+        ExternalResource resource = resourceDAO.find("ws-target-resource-2");
+        assertNotNull(resource);
+        assertEquals("fullname", resource.getUmapping().getAccountIdItem().getIntAttrName());
+    }
+
+    @Test
+    public void save() {
+        ExternalResource resource = new JPAExternalResource();
+        resource.setKey("ws-target-resource-basic-save");
+        resource.setPropagationPriority(2);
+        resource.setPropagationPrimary(true);
+
+        UMapping mapping = new JPAUMapping();
+        resource.setUmapping(mapping);
+
+        UMappingItem accountId = new JPAUMappingItem();
+        accountId.setExtAttrName("username");
+        accountId.setIntAttrName("fullname");
+        accountId.setIntMappingType(IntMappingType.UserId);
+        accountId.setPurpose(MappingPurpose.BOTH);
+        mapping.setAccountIdItem(accountId);
+
+        ConnInstance connector = resourceDAO.find("ws-target-resource-1").getConnector();
+        resource.setConnector(connector);
+
+        // save the resource
+        ExternalResource actual = resourceDAO.save(resource);
+
+        assertNotNull(actual);
+        assertNotNull(actual.getConnector());
+        assertNotNull(actual.getUmapping());
+        assertFalse(actual.getUmapping().getItems().isEmpty());
+        assertEquals(Integer.valueOf(2), actual.getPropagationPriority());
+        assertTrue(actual.isPropagationPrimary());
+    }
+
+    @Test(expected = InvalidEntityException.class)
+    public void saveInvalidMappingIntAttr() {
+        ExternalResource resource = new JPAExternalResource();
+        resource.setKey("ws-target-resource-basic-save-invalid");
+
+        ConnInstance connector = resourceDAO.find("ws-target-resource-1").getConnector();
+        resource.setConnector(connector);
+
+        UMapping mapping = new JPAUMapping();
+        resource.setUmapping(mapping);
+
+        UMappingItem accountId = new JPAUMappingItem();
+        accountId.setAccountid(true);
+        accountId.setIntMappingType(IntMappingType.UserSchema);
+        mapping.addItem(accountId);
+
+        // save the resource
+        ExternalResource actual = resourceDAO.save(resource);
+        assertNotNull(actual);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void saveInvalidAccountIdMapping() {
+        ExternalResource resource = new JPAExternalResource();
+        resource.setKey("ws-target-resource-basic-save-invalid");
+
+        ConnInstance connector = resourceDAO.find("ws-target-resource-1").getConnector();
+        resource.setConnector(connector);
+
+        UMapping mapping = new JPAUMapping();
+        resource.setUmapping(mapping);
+
+        UMappingItem accountId = new JPAUMappingItem();
+        accountId.setAccountid(true);
+        accountId.setIntMappingType(IntMappingType.UserVirtualSchema);
+        mapping.setAccountIdItem(accountId);
+
+        // save the resource
+        ExternalResource actual = resourceDAO.save(resource);
+        assertNotNull(actual);
+    }
+
+    @Test(expected = InvalidEntityException.class)
+    public void saveInvalidMappingExtAttr() {
+        ExternalResource resource = new JPAExternalResource();
+        resource.setKey("ws-target-resource-basic-save-invalid");
+
+        ConnInstance connector = resourceDAO.find("ws-target-resource-1").getConnector();
+        resource.setConnector(connector);
+
+        UMapping mapping = new JPAUMapping();
+        resource.setUmapping(mapping);
+
+        UMappingItem item = new JPAUMappingItem();
+        item.setAccountid(true);
+        item.setIntAttrName("fullname");
+        item.setIntMappingType(IntMappingType.UserSchema);
+        mapping.addItem(item);
+
+        item = new JPAUMappingItem();
+        item.setIntAttrName("userId");
+        item.setIntMappingType(IntMappingType.UserSchema);
+        mapping.addItem(item);
+
+        ExternalResource actual = resourceDAO.save(resource);
+        assertNotNull(actual);
+    }
+
+    @Test
+    public void saveWithRoleMappingType() {
+        ExternalResource resource = new JPAExternalResource();
+        resource.setKey("ws-target-resource-basic-save-invalid");
+
+        ConnInstance connector = resourceDAO.find("ws-target-resource-1").getConnector();
+        resource.setConnector(connector);
+
+        UMapping mapping = new JPAUMapping();
+        resource.setUmapping(mapping);
+
+        UMappingItem item = new JPAUMappingItem();
+        item.setIntAttrName("fullname");
+        item.setExtAttrName("fullname");
+        item.setIntMappingType(IntMappingType.UserSchema);
+        item.setPurpose(MappingPurpose.BOTH);
+        mapping.setAccountIdItem(item);
+
+        item = new JPAUMappingItem();
+        item.setIntAttrName("icon");
+        item.setExtAttrName("icon");
+        item.setIntMappingType(IntMappingType.RoleSchema);
+        item.setPurpose(MappingPurpose.BOTH);
+        mapping.addItem(item);
+
+        item = new JPAUMappingItem();
+        item.setIntAttrName("mderiveddata");
+        item.setExtAttrName("mderiveddata");
+        item.setIntMappingType(IntMappingType.MembershipDerivedSchema);
+        item.setPurpose(MappingPurpose.BOTH);
+        mapping.addItem(item);
+
+        // save the resource
+        ExternalResource actual = resourceDAO.save(resource);
+        assertNotNull(actual);
+
+        int items = 0;
+        for (UMappingItem mapItem : actual.getUmapping().getItems()) {
+            items++;
+
+            if ("icon".equals(mapItem.getIntAttrName())) {
+                assertTrue(IntMappingType.contains(AttributableType.ROLE,
+                        mapItem.getIntMappingType().toString()));
+            }
+            if ("mderiveddata".equals(mapItem.getIntAttrName())) {
+                assertTrue(IntMappingType.contains(AttributableType.MEMBERSHIP,
+                        mapItem.getIntMappingType().toString()));
+            }
+        }
+        assertEquals(3, items);
+    }
+
+    @Test
+    public void delete() {
+        ExternalResource resource = resourceDAO.find("ws-target-resource-2");
+        assertNotNull(resource);
+
+        resourceDAO.delete(resource.getKey());
+
+        ExternalResource actual = resourceDAO.find("ws-target-resource-2");
+        assertNull(actual);
+    }
+
+    @Test
+    public void issueSYNCOPE418() {
+        ExternalResource resource = new JPAExternalResource();
+        resource.setKey("http://schemas.examples.org/security/authorization/organizationUnit");
+
+        try {
+            resourceDAO.save(resource);
+            fail();
+        } catch (InvalidEntityException e) {
+            assertTrue(e.hasViolation(EntityViolationType.InvalidName));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/RoleTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/RoleTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/RoleTest.java
new file mode 100644
index 0000000..da5256f
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/RoleTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.List;
+import org.apache.syncope.persistence.api.dao.PolicyDAO;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.entity.AccountPolicy;
+import org.apache.syncope.persistence.api.entity.PasswordPolicy;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.role.JPARole;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class RoleTest extends AbstractTest {
+
+    @Autowired
+    private RoleDAO roleDAO;
+
+    @Autowired
+    private PolicyDAO policyDAO;
+
+    @Test
+    public void findAll() {
+        List<Role> list = roleDAO.findAll();
+        assertEquals("did not get expected number of roles ", 14, list.size());
+    }
+
+    @Test
+    public void findChildren() {
+        assertEquals(3, roleDAO.findChildren(roleDAO.find(4L)).size());
+    }
+
+    @Test
+    public void find() {
+        Role role = roleDAO.find("root", null);
+        assertNotNull("did not find expected role", role);
+        role = roleDAO.find(null, null);
+        assertNull("found role but did not expect it", role);
+    }
+
+    @Test
+    public void inheritedAttributes() {
+        Role director = roleDAO.find(7L);
+
+        assertEquals(1, director.findLastInheritedAncestorPlainAttrs().size());
+    }
+
+    @Test
+    public void inheritedDerivedAttributes() {
+        Role director = roleDAO.find(7L);
+
+        assertEquals(1, director.findLastInheritedAncestorDerAttrs().size());
+    }
+
+    @Test
+    public void inheritedVirtualAttributes() {
+        Role director = roleDAO.find(7L);
+
+        assertEquals(1, director.findLastInheritedAncestorVirAttrs().size());
+    }
+
+    @Test
+    public void inheritedPolicy() {
+        Role role = roleDAO.find(7L);
+
+        assertNotNull(role);
+
+        assertNotNull(role.getAccountPolicy());
+        assertNotNull(role.getPasswordPolicy());
+
+        assertEquals(4, role.getPasswordPolicy().getKey(), 0);
+
+        role = roleDAO.find(5L);
+
+        assertNotNull(role);
+
+        assertNull(role.getAccountPolicy());
+        assertNull(role.getPasswordPolicy());
+    }
+
+    @Test
+    public void save() {
+        Role role = new JPARole();
+        role.setName("secondChild");
+
+        // verify inheritance password and account policies
+        role.setInheritAccountPolicy(false);
+        // not inherited so setter execution shouldn't be ignored
+        role.setAccountPolicy((AccountPolicy) policyDAO.find(6L));
+
+        role.setInheritPasswordPolicy(true);
+        // inherited so setter execution should be ignored
+        role.setPasswordPolicy((PasswordPolicy) policyDAO.find(4L));
+
+        Role rootRole = roleDAO.find("root", null);
+        role.setParent(rootRole);
+
+        role = roleDAO.save(role);
+
+        Role actual = roleDAO.find(role.getKey());
+        assertNotNull("expected save to work", actual);
+
+        assertNull(role.getPasswordPolicy());
+        assertNotNull(role.getAccountPolicy());
+        assertEquals(Long.valueOf(6), role.getAccountPolicy().getKey());
+    }
+
+    @Test
+    public void delete() {
+        Role role = roleDAO.find(4L);
+        roleDAO.delete(role.getKey());
+
+        Role actual = roleDAO.find(4L);
+        assertNull("delete did not work", actual);
+
+        Role children = roleDAO.find(7L);
+        assertNull("delete of successors did not work", children);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/SecurityQuestionTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/SecurityQuestionTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/SecurityQuestionTest.java
new file mode 100644
index 0000000..61b210f
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/SecurityQuestionTest.java
@@ -0,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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.List;
+import org.apache.syncope.persistence.api.dao.SecurityQuestionDAO;
+import org.apache.syncope.persistence.api.entity.user.SecurityQuestion;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class SecurityQuestionTest extends AbstractTest {
+
+    @Autowired
+    private SecurityQuestionDAO securityQuestionDAO;
+
+    @Test
+    public void find() {
+        SecurityQuestion securityQuestion = securityQuestionDAO.find(1L);
+        assertNotNull(securityQuestion);
+        assertNotNull(securityQuestion.getContent());
+    }
+
+    @Test
+    public void findAll() {
+        List<SecurityQuestion> securityQuestions = securityQuestionDAO.findAll();
+        assertNotNull(securityQuestions);
+        assertFalse(securityQuestions.isEmpty());
+    }
+
+    @Test
+    public void save() {
+        SecurityQuestion securityQuestion = new JPASecurityQuestion();
+        securityQuestion.setContent("What is your favorite pet's name?");
+
+        SecurityQuestion actual = securityQuestionDAO.save(securityQuestion);
+        assertNotNull(actual);
+        assertNotNull(actual.getKey());
+    }
+
+    @Test
+    public void delete() {
+        securityQuestionDAO.delete(1L);
+        assertNull(securityQuestionDAO.find(1L));
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/TaskExecTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/TaskExecTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/TaskExecTest.java
new file mode 100644
index 0000000..bbf4123
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/TaskExecTest.java
@@ -0,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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Date;
+import java.util.List;
+import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.persistence.api.dao.TaskDAO;
+import org.apache.syncope.persistence.api.dao.TaskExecDAO;
+import org.apache.syncope.persistence.api.entity.task.PropagationTask;
+import org.apache.syncope.persistence.api.entity.task.TaskExec;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.task.JPATaskExec;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class TaskExecTest extends AbstractTest {
+
+    @Autowired
+    private TaskExecDAO taskExecDAO;
+
+    @Autowired
+    private TaskDAO taskDAO;
+
+    @Test
+    public void findAll() {
+        List<TaskExec> list = taskExecDAO.findAll(TaskType.PROPAGATION);
+        assertEquals(2, list.size());
+
+        list = taskExecDAO.findAll(TaskType.SCHEDULED);
+        assertTrue(list.isEmpty());
+
+        list = taskExecDAO.findAll(TaskType.SYNCHRONIZATION);
+        assertTrue(list.isEmpty());
+
+        list = taskExecDAO.findAll(TaskType.NOTIFICATION);
+        assertTrue(list.isEmpty());
+    }
+
+    @Test
+    public void findLatestStarted() {
+        PropagationTask task = taskDAO.find(1L);
+        assertNotNull(task);
+
+        TaskExec latestStarted = taskExecDAO.findLatestStarted(task);
+        assertNotNull(latestStarted);
+        assertEquals(Long.valueOf(1L), latestStarted.getKey());
+    }
+
+    @Test
+    public void issueSYNCOPE214() {
+        PropagationTask task = taskDAO.find(1L);
+        assertNotNull(task);
+
+        String faultyMessage = "A faulty message";
+        faultyMessage = faultyMessage.replace('a', '\0');
+
+        TaskExec exec = new JPATaskExec();
+        exec.setStartDate(new Date());
+        exec.setEndDate(new Date());
+        exec.setStatus(PropagationTaskExecStatus.SUCCESS.name());
+        exec.setMessage(faultyMessage);
+
+        task.addExec(exec);
+        exec.setTask(task);
+
+        exec = taskExecDAO.save(exec);
+        assertNotNull(exec);
+
+        assertEquals(faultyMessage.replace('\0', '\n'), exec.getMessage());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/TaskTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/TaskTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/TaskTest.java
new file mode 100644
index 0000000..3154b35
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/TaskTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.PropagationMode;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.persistence.api.dao.ExternalResourceDAO;
+import org.apache.syncope.persistence.api.dao.TaskDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.task.PropagationTask;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.task.JPAPropagationTask;
+import org.identityconnectors.framework.common.objects.Attribute;
+import org.identityconnectors.framework.common.objects.AttributeBuilder;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class TaskTest extends AbstractTest {
+
+    @Autowired
+    private TaskDAO taskDAO;
+
+    @Autowired
+    private ExternalResourceDAO resourceDAO;
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Test
+    public void findWithoutExecs() {
+        List<PropagationTask> tasks = taskDAO.findToExec(TaskType.PROPAGATION);
+        assertNotNull(tasks);
+        assertEquals(2, tasks.size());
+    }
+
+    @Test
+    public void findAll() {
+        assertEquals(4, taskDAO.findAll(TaskType.PROPAGATION).size());
+        assertEquals(1, taskDAO.findAll(TaskType.NOTIFICATION).size());
+        assertEquals(1, taskDAO.findAll(TaskType.SCHEDULED).size());
+        assertEquals(9, taskDAO.findAll(TaskType.SYNCHRONIZATION).size());
+        assertEquals(11, taskDAO.findAll(TaskType.PUSH).size());
+    }
+
+    @Test
+    public void savePropagationTask() {
+        ExternalResource resource = resourceDAO.find("ws-target-resource-1");
+        assertNotNull(resource);
+
+        User user = userDAO.find(2L);
+        assertNotNull(user);
+
+        PropagationTask task = new JPAPropagationTask();
+        task.setResource(resource);
+        task.setSubjectType(AttributableType.USER);
+        task.setPropagationMode(PropagationMode.TWO_PHASES);
+        task.setPropagationOperation(ResourceOperation.CREATE);
+        task.setAccountId("one@two.com");
+
+        Set<Attribute> attributes = new HashSet<Attribute>();
+        attributes.add(AttributeBuilder.build("testAttribute", "testValue1", "testValue2"));
+        attributes.add(AttributeBuilder.buildPassword("password".toCharArray()));
+        task.setAttributes(attributes);
+
+        task = taskDAO.save(task);
+        assertNotNull(task);
+
+        PropagationTask actual = taskDAO.find(task.getKey());
+        assertEquals(task, actual);
+    }
+
+    @Test
+    public void delete() {
+        PropagationTask task = taskDAO.find(1L);
+        assertNotNull(task);
+
+        ExternalResource resource = task.getResource();
+        assertNotNull(resource);
+
+        taskDAO.delete(task);
+        task = taskDAO.find(1L);
+        assertNull(task);
+
+        resource = resourceDAO.find(resource.getKey());
+        assertNotNull(resource);
+        assertFalse(taskDAO.findAll(resource, TaskType.PROPAGATION).contains(task));
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/UserTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/UserTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/UserTest.java
new file mode 100644
index 0000000..3acb870
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/UserTest.java
@@ -0,0 +1,213 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+import org.apache.syncope.common.lib.types.CipherAlgorithm;
+import org.apache.syncope.persistence.api.RoleEntitlementUtil;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.dao.EntitlementDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttrValue;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUPlainAttrValue;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUser;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class UserTest extends AbstractTest {
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Autowired
+    private EntitlementDAO entitlementDAO;
+
+    @Test
+    public void findAll() {
+        List<User> list = userDAO.findAll(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), 1, 100);
+        assertEquals("did not get expected number of users ", 5, list.size());
+    }
+
+    @Test
+    public void count() {
+        Integer count = userDAO.count(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()));
+        assertNotNull(count);
+        assertEquals(5, count.intValue());
+    }
+
+    @Test
+    public void findAllByPageAndSize() {
+        Set<Long> allRoleIds = RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll());
+
+        // get first page
+        List<User> list = userDAO.findAll(allRoleIds, 1, 2);
+        assertEquals("did not get expected number of users ", 2, list.size());
+
+        // get second page
+        list = userDAO.findAll(allRoleIds, 2, 2);
+        assertEquals("did not get expected number of users ", 2, list.size());
+
+        // get second page with uncomplete set
+        list = userDAO.findAll(allRoleIds, 2, 3);
+        assertEquals("did not get expected number of users ", 2, list.size());
+
+        // get unexistent page
+        list = userDAO.findAll(allRoleIds, 3, 2);
+        assertEquals("did not get expected number of users ", 1, list.size());
+    }
+
+    @Test
+    public void findByDerAttributeValue() {
+        final List<User> list = userDAO.findByDerAttrValue("cn", "Vivaldi, Antonio");
+        assertEquals("did not get expected number of users ", 1, list.size());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void findByInvalidDerAttrValue() {
+        userDAO.findByDerAttrValue("cn", "Antonio, Maria, Rossi");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void findByInvalidDerAttrExpression() {
+        userDAO.findByDerAttrValue("noschema", "Antonio, Maria");
+    }
+
+    @Test
+    public void findByAttributeValue() {
+        final UPlainAttrValue fullnameValue = new JPAUPlainAttrValue();
+        fullnameValue.setStringValue("Gioacchino Rossini");
+
+        final List<User> list = userDAO.findByAttrValue("fullname", fullnameValue);
+        assertEquals("did not get expected number of users ", 1, list.size());
+    }
+
+    @Test
+    public void findByAttributeBooleanValue() {
+        final UPlainAttrValue coolValue = new JPAUPlainAttrValue();
+        coolValue.setBooleanValue(true);
+
+        final List<User> list = userDAO.findByAttrValue("cool", coolValue);
+        assertEquals("did not get expected number of users ", 1, list.size());
+    }
+
+    @Test
+    public void findById() {
+        User user = userDAO.find(1L);
+        assertNotNull("did not find expected user", user);
+        user = userDAO.find(3L);
+        assertNotNull("did not find expected user", user);
+        user = userDAO.find(6L);
+        assertNull("found user but did not expect it", user);
+    }
+
+    @Test
+    public void findByUsername() {
+        User user = userDAO.find("rossini");
+        assertNotNull("did not find expected user", user);
+        user = userDAO.find("vivaldi");
+        assertNotNull("did not find expected user", user);
+        user = userDAO.find("user6");
+        assertNull("found user but did not expect it", user);
+    }
+
+    @Test
+    public void save() {
+        User user = new JPAUser();
+        user.setUsername("username");
+        user.setCreationDate(new Date());
+
+        user.setPassword("pass", CipherAlgorithm.SHA256);
+
+        Throwable t = null;
+        try {
+            userDAO.save(user);
+        } catch (InvalidEntityException e) {
+            t = e;
+        }
+        assertNotNull(t);
+
+        user.setPassword("password", CipherAlgorithm.SHA256);
+
+        user.setUsername("username!");
+
+        t = null;
+        try {
+            userDAO.save(user);
+        } catch (InvalidEntityException e) {
+            t = e;
+        }
+        assertNotNull(t);
+
+        user.setUsername("username");
+
+        User actual = userDAO.save(user);
+        assertNotNull("expected save to work", actual);
+        assertEquals(1, actual.getPasswordHistory().size());
+    }
+
+    @Test
+    public void delete() {
+        User user = userDAO.find(3L);
+
+        userDAO.delete(user.getKey());
+
+        User actual = userDAO.find(3L);
+        assertNull("delete did not work", actual);
+    }
+
+    @Test
+    public void issue237() {
+        User user = new JPAUser();
+        user.setUsername("username");
+        user.setCreationDate(new Date());
+
+        user.setPassword("password", CipherAlgorithm.AES);
+
+        User actual = userDAO.save(user);
+        assertNotNull(actual);
+    }
+
+    @Test
+    public void issueSYNCOPE391() {
+        User user = new JPAUser();
+        user.setUsername("username");
+        user.setPassword(null, CipherAlgorithm.AES);
+
+        User actual = null;
+        Throwable t = null;
+        try {
+            actual = userDAO.save(user);
+        } catch (InvalidEntityException e) {
+            t = e;
+        }
+        assertNull(t);
+        assertNull(user.getPassword());
+        assertNotNull(actual);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/VirAttrTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/VirAttrTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/VirAttrTest.java
new file mode 100644
index 0000000..07cd61a
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/VirAttrTest.java
@@ -0,0 +1,145 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.List;
+import org.apache.syncope.persistence.api.dao.MembershipDAO;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.dao.VirAttrDAO;
+import org.apache.syncope.persistence.api.dao.VirSchemaDAO;
+import org.apache.syncope.persistence.api.entity.membership.MVirAttr;
+import org.apache.syncope.persistence.api.entity.membership.MVirAttrTemplate;
+import org.apache.syncope.persistence.api.entity.membership.Membership;
+import org.apache.syncope.persistence.api.entity.role.RVirAttr;
+import org.apache.syncope.persistence.api.entity.role.RVirAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.api.entity.user.UVirAttr;
+import org.apache.syncope.persistence.api.entity.user.UVirSchema;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMVirAttr;
+import org.apache.syncope.persistence.jpa.entity.role.JPARVirAttr;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUVirAttr;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class VirAttrTest extends AbstractTest {
+
+    @Autowired
+    private VirAttrDAO virAttrDAO;
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Autowired
+    private RoleDAO roleDAO;
+
+    @Autowired
+    private MembershipDAO membershipDAO;
+
+    @Autowired
+    private VirSchemaDAO virSchemaDAO;
+
+    @Test
+    public void findAll() {
+        List<UVirAttr> list = virAttrDAO.findAll(UVirAttr.class);
+        assertEquals("did not get expected number of derived attributes ", 1, list.size());
+    }
+
+    @Test
+    public void findById() {
+        UVirAttr attribute = virAttrDAO.find(1000L, UVirAttr.class);
+        assertNotNull("did not find expected attribute schema", attribute);
+    }
+
+    @Test
+    public void saveUVirAttribute() {
+        UVirSchema virSchema = virSchemaDAO.find("virtualdata", UVirSchema.class);
+        assertNotNull(virSchema);
+
+        User owner = userDAO.find(3L);
+        assertNotNull("did not get expected user", owner);
+
+        UVirAttr virAttr = new JPAUVirAttr();
+        virAttr.setOwner(owner);
+        virAttr.setSchema(virSchema);
+
+        virAttr = virAttrDAO.save(virAttr);
+
+        UVirAttr actual = virAttrDAO.find(virAttr.getKey(), UVirAttr.class);
+        assertNotNull("expected save to work", actual);
+        assertEquals(virAttr, actual);
+    }
+
+    @Test
+    public void saveMVirAttribute() {
+        Membership owner = membershipDAO.find(3L);
+        assertNotNull("did not get expected membership", owner);
+
+        MVirAttr virAttr = new JPAMVirAttr();
+        virAttr.setOwner(owner);
+        virAttr.setTemplate(owner.getRole().getAttrTemplate(MVirAttrTemplate.class, "mvirtualdata"));
+
+        virAttr = virAttrDAO.save(virAttr);
+        assertNotNull(virAttr.getTemplate());
+
+        MVirAttr actual = virAttrDAO.find(virAttr.getKey(), MVirAttr.class);
+        assertNotNull("expected save to work", actual);
+        assertEquals(virAttr, actual);
+    }
+
+    @Test
+    public void saveRVirAttribute() {
+        Role owner = roleDAO.find(3L);
+        assertNotNull("did not get expected membership", owner);
+
+        RVirAttr virAttr = new JPARVirAttr();
+        virAttr.setOwner(owner);
+        virAttr.setTemplate(owner.getAttrTemplate(RVirAttrTemplate.class, "rvirtualdata"));
+
+        virAttr = virAttrDAO.save(virAttr);
+        assertNotNull(virAttr.getTemplate());
+
+        RVirAttr actual = virAttrDAO.find(virAttr.getKey(), RVirAttr.class);
+        assertNotNull("expected save to work", actual);
+        assertEquals(virAttr, actual);
+    }
+
+    @Test
+    public void delete() {
+        UVirAttr attribute = virAttrDAO.find(1000L, UVirAttr.class);
+        String attributeSchemaName = attribute.getSchema().getKey();
+
+        virAttrDAO.delete(attribute.getKey(), UVirAttr.class);
+
+        UVirAttr actual = virAttrDAO.find(1000L, UVirAttr.class);
+        assertNull("delete did not work", actual);
+
+        UVirSchema attributeSchema = virSchemaDAO.find(attributeSchemaName, UVirSchema.class);
+
+        assertNotNull("user virtual attribute schema deleted " + "when deleting values", attributeSchema);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/VirSchemaTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/VirSchemaTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/VirSchemaTest.java
new file mode 100644
index 0000000..4cf9be8
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/VirSchemaTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.List;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.dao.VirSchemaDAO;
+import org.apache.syncope.persistence.api.entity.VirSchema;
+import org.apache.syncope.persistence.api.entity.role.RVirSchema;
+import org.apache.syncope.persistence.api.entity.user.UVirSchema;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUVirSchema;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class VirSchemaTest extends AbstractTest {
+
+    @Autowired
+    private VirSchemaDAO virSchemaDAO;
+
+    @Test
+    public void findAll() {
+        List<UVirSchema> list = virSchemaDAO.findAll(UVirSchema.class);
+        assertEquals(2, list.size());
+    }
+
+    @Test
+    public void findByName() {
+        UVirSchema attributeSchema = virSchemaDAO.find("virtualdata", UVirSchema.class);
+        assertNotNull("did not find expected virtual attribute schema", attributeSchema);
+    }
+
+    @Test
+    public void save() {
+        UVirSchema virtualAttributeSchema = new JPAUVirSchema();
+        virtualAttributeSchema.setKey("virtual");
+        virtualAttributeSchema.setReadonly(true);
+
+        virSchemaDAO.save(virtualAttributeSchema);
+
+        UVirSchema actual = virSchemaDAO.find("virtual", UVirSchema.class);
+        assertNotNull("expected save to work", actual);
+        assertTrue(actual.isReadonly());
+    }
+
+    @Test
+    public void delete() {
+        UVirSchema virtualdata = virSchemaDAO.find("virtualdata", UVirSchema.class);
+
+        virSchemaDAO.delete(virtualdata.getKey(), JPAAttributableUtil.getInstance(AttributableType.USER));
+
+        VirSchema actual = virSchemaDAO.find("virtualdata", UVirSchema.class);
+        assertNull("delete did not work", actual);
+
+        // ------------- //
+        RVirSchema rvirtualdata = virSchemaDAO.find("rvirtualdata", RVirSchema.class);
+        assertNotNull(rvirtualdata);
+
+        virSchemaDAO.delete(rvirtualdata.getKey(), JPAAttributableUtil.getInstance(AttributableType.ROLE));
+
+        actual = virSchemaDAO.find("rvirtualdata", RVirSchema.class);
+        assertNull("delete did not work", actual);
+    }
+
+    @Test
+    public void issueSYNCOPE418() {
+        UVirSchema schema = new JPAUVirSchema();
+        schema.setKey("http://schemas.examples.org/security/authorization/organizationUnit");
+
+        try {
+            virSchemaDAO.save(schema);
+            fail();
+        } catch (InvalidEntityException e) {
+            assertTrue(e.hasViolation(EntityViolationType.InvalidName));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/EntitlementTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/EntitlementTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/EntitlementTest.java
new file mode 100644
index 0000000..077a8e2
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/relationship/EntitlementTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.persistence.jpa.relationship;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+import org.apache.syncope.persistence.api.dao.EntitlementDAO;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.entity.Entitlement;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class EntitlementTest extends AbstractTest {
+
+    @Autowired
+    private EntitlementDAO entitlementDAO;
+
+    @Autowired
+    private RoleDAO roleDAO;
+
+    @Test
+    public void delete() {
+        Entitlement entitlement = entitlementDAO.find("base");
+        assertNotNull("did not find expected entitlement", entitlement);
+
+        List<Role> roles = roleDAO.findByEntitlement(entitlement);
+        assertEquals("expected two roles", 2, roles.size());
+
+        entitlementDAO.delete("base");
+
+        roles = roleDAO.findByEntitlement(entitlement);
+        assertTrue(roles.isEmpty());
+    }
+}


[03/32] syncope git commit: [SYNOPE-610][SYNCOPE-616] Fixing and improving the management of the xml and properties files inside the installer

Posted by il...@apache.org.
[SYNOPE-610][SYNCOPE-616] Fixing and improving the management of the xml and properties files inside the installer


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

Branch: refs/heads/2_0_X
Commit: 5e013aa44bec914bb27115105f0585e6437c8316
Parents: 4a2e843
Author: Marco Di Sabatino Di Diodoro <md...@apache.org>
Authored: Mon Dec 22 17:56:11 2014 +0100
Committer: Marco Di Sabatino Di Diodoro <md...@apache.org>
Committed: Mon Dec 22 17:56:11 2014 +0100

----------------------------------------------------------------------
 installer/pom.xml                               |  20 +++
 .../installer/containers/jboss/JBoss.java       |  12 +-
 .../org/apache/syncope/installer/enums/DBs.java |   3 +
 .../installer/files/ConsoleProperties.java      |  31 ++++
 .../syncope/installer/files/CoreWebXml.java     |  76 ++------
 .../installer/files/GlassfishCoreWebXml.java    |  38 +---
 .../files/JBossDeploymentStructureXml.java      |  40 +----
 .../syncope/installer/files/ParentPom.java      | 176 +------------------
 .../files/PersistenceContextEMFactoryXml.java   |  47 +----
 .../installer/files/PersistenceProperties.java  |  27 +--
 .../installer/processes/ArchetypeProcess.java   |  41 +++--
 .../installer/processes/BaseProcess.java        |  54 ++++++
 .../installer/processes/ContainerProcess.java   | 171 ++++++++++++++----
 .../installer/processes/PersistenceProcess.java |  25 ++-
 .../installer/utilities/FileSystemUtils.java    |  45 +++++
 .../syncope/installer/utilities/MavenUtils.java |  31 +---
 .../src/main/resources/configuration.properties |  31 ++++
 .../main/resources/izpack/ProcessPanel.Spec.xml |  40 +++--
 installer/src/main/resources/izpack/install.xml |   6 +-
 .../main/resources/izpack/userInputLang.xml_eng |   4 +
 .../main/resources/izpack/userInputLang.xml_ita |   4 +
 .../src/main/resources/izpack/userInputSpec.xml |  20 ++-
 installer/src/main/resources/modelerPom.xml     | 116 ++++++++++++
 23 files changed, 589 insertions(+), 469 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/pom.xml
----------------------------------------------------------------------
diff --git a/installer/pom.xml b/installer/pom.xml
index e6675de..7f6e8b0 100644
--- a/installer/pom.xml
+++ b/installer/pom.xml
@@ -173,6 +173,18 @@ under the License.
 
     <resources>
       <resource>
+        <directory>${basedir}/../core/src/main/resources/</directory>
+        <includes>
+          <include>**/orm*</include>
+        </includes>
+      </resource>
+      <resource>
+        <directory>${basedir}/../core/src/test/resources/</directory>
+        <includes>
+          <include>**/persistenceContextEMFactory.xml</include>
+        </includes>
+      </resource>
+      <resource>
         <directory>${basedir}</directory>
         <targetPath>META-INF</targetPath>
         <includes>
@@ -180,6 +192,14 @@ under the License.
           <include>NOTICE</include>
         </includes>
       </resource>
+      <resource>
+        <directory>src/main/resources</directory>
+        <includes>
+          <include>**/configuration.properties</include>
+          <include>**/modelerPom.xml</include>
+        </includes>
+        <filtering>true</filtering>
+      </resource>
     </resources>
   </build>
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/java/org/apache/syncope/installer/containers/jboss/JBoss.java
----------------------------------------------------------------------
diff --git a/installer/src/main/java/org/apache/syncope/installer/containers/jboss/JBoss.java b/installer/src/main/java/org/apache/syncope/installer/containers/jboss/JBoss.java
index c3f7429..c0e6722 100644
--- a/installer/src/main/java/org/apache/syncope/installer/containers/jboss/JBoss.java
+++ b/installer/src/main/java/org/apache/syncope/installer/containers/jboss/JBoss.java
@@ -33,7 +33,7 @@ public class JBoss extends AbstractContainer {
 
     private final String jbossHost;
 
-    private final String jbossPort;
+    private final String jbossManagementPort;
 
     private final String installPath;
 
@@ -41,15 +41,15 @@ public class JBoss extends AbstractContainer {
 
     private final HttpUtils httpUtils;
 
-    public JBoss(final boolean jbossSsl, final String jbossHost, final String jbossPort,
+    public JBoss(final boolean jbossSsl, final String jbossHost, final String jbossManagementPort,
             final String jbossAdminUsername, final String jbossAdminPassword,
             final String installPath, final String artifactId, final AbstractUIProcessHandler handler) {
         this.jbossSsl = jbossSsl;
         this.jbossHost = jbossHost;
-        this.jbossPort = jbossPort;
+        this.jbossManagementPort = jbossManagementPort;
         this.installPath = installPath;
         this.artifactId = artifactId;
-        httpUtils = new HttpUtils(jbossSsl, jbossHost, jbossPort, jbossAdminUsername, jbossAdminPassword, handler);
+        httpUtils = new HttpUtils(jbossSsl, jbossHost, jbossManagementPort, jbossAdminUsername, jbossAdminPassword, handler);
 
     }
 
@@ -63,7 +63,7 @@ public class JBoss extends AbstractContainer {
 
     public boolean deploy(final String whatDeploy, final String warName) {
         final String responseBodyAsString = httpUtils.postWithDigestAuth(
-                String.format(addContentUrl, jbossHost, jbossPort),
+                String.format(addContentUrl, jbossHost, jbossManagementPort),
                 String.format(whatDeploy, installPath, artifactId));
 
         final JBossAddResponse jBossAddResponse = JsonUtils.jBossAddResponse(responseBodyAsString);
@@ -72,7 +72,7 @@ public class JBoss extends AbstractContainer {
                 jBossAddResponse.getResult().getBYTES_VALUE(), warName);
 
         int status = httpUtils.
-                postWithStringEntity(String.format(enableUrl, jbossHost, jbossPort),
+                postWithStringEntity(String.format(enableUrl, jbossHost, jbossManagementPort),
                         JsonUtils.jBossDeployRequestContent(jBossDeployRequestContent));
         return status == 200;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/java/org/apache/syncope/installer/enums/DBs.java
----------------------------------------------------------------------
diff --git a/installer/src/main/java/org/apache/syncope/installer/enums/DBs.java b/installer/src/main/java/org/apache/syncope/installer/enums/DBs.java
index 714e888..db7f8ec 100644
--- a/installer/src/main/java/org/apache/syncope/installer/enums/DBs.java
+++ b/installer/src/main/java/org/apache/syncope/installer/enums/DBs.java
@@ -43,7 +43,10 @@ public enum DBs {
             db = MYSQL;
         } else if (ORACLE.getName().equalsIgnoreCase(containerName)) {
             db = ORACLE;
+        } else {
+            db = SQLSERVER;
         }
+
         return db;
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/java/org/apache/syncope/installer/files/ConsoleProperties.java
----------------------------------------------------------------------
diff --git a/installer/src/main/java/org/apache/syncope/installer/files/ConsoleProperties.java b/installer/src/main/java/org/apache/syncope/installer/files/ConsoleProperties.java
new file mode 100644
index 0000000..d6d2deb
--- /dev/null
+++ b/installer/src/main/java/org/apache/syncope/installer/files/ConsoleProperties.java
@@ -0,0 +1,31 @@
+/*
+ * 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.installer.files;
+
+public class ConsoleProperties {
+
+    public static final String PLACEHOLDER = "scheme=http\n"
+            + "host=localhost\n"
+            + "port=8080";
+
+    public static final String CONSOLE = "scheme=%s\n"
+            + "host=%s\n"
+            + "port=%s";
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/java/org/apache/syncope/installer/files/CoreWebXml.java
----------------------------------------------------------------------
diff --git a/installer/src/main/java/org/apache/syncope/installer/files/CoreWebXml.java b/installer/src/main/java/org/apache/syncope/installer/files/CoreWebXml.java
index a22c79a..1f78dbc 100644
--- a/installer/src/main/java/org/apache/syncope/installer/files/CoreWebXml.java
+++ b/installer/src/main/java/org/apache/syncope/installer/files/CoreWebXml.java
@@ -20,78 +20,30 @@ package org.apache.syncope.installer.files;
 
 public class CoreWebXml {
 
-    public static final String PATH = "/core/src/main/webapp/WEB-INF/web.xml";
+    public static final String PLACEHOLDER = "</web-app>";
 
-    public static String withDataSource() {
-        return String.format(FILE, withDataSource);
-    }
-
-    public static String withDataSourceForJBoss() {
-        return String.format(FILE, withDataSourceForJBoss);
-    }
-
-    private static final String FILE = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<!--\n"
-            + "Licensed to the Apache Software Foundation (ASF) under one\n"
-            + "or more contributor license agreements.  See the NOTICE file\n"
-            + "distributed with this work for additional information\n"
-            + "regarding copyright ownership.  The ASF licenses this file\n"
-            + "to you under the Apache License, Version 2.0 (the\n"
-            + "\"License\"); you may not use this file except in compliance\n"
-            + "with the License.  You may obtain a copy of the License at\n" + "\n"
-            + "  http://www.apache.org/licenses/LICENSE-2.0\n" + "\n"
-            + "Unless required by applicable law or agreed to in writing,\n"
-            + "software distributed under the License is distributed on an\n"
-            + "\"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n"
-            + "KIND, either express or implied.  See the License for the\n"
-            + "specific language governing permissions and limitations\n" + "under the License.\n" + "-->\n"
-            + "<web-app xmlns=\"http://java.sun.com/xml/ns/javaee\"\n"
-            + "         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
-            + "         xsi:schemaLocation=\"http://java.sun.com/xml/ns/javaee \n"
-            + "                             http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd\"\n"
-            + "         version=\"3.0\">\n" + "\n" + "  <display-name>Apache Syncope core</display-name>\n" + "\n"
-            + "  <context-param>\n" + "    <param-name>contextConfigLocation</param-name>\n"
-            + "    <param-value>classpath*:/*Context.xml</param-value>\n" + "  </context-param>\n" + "\n"
-            + "  <listener>\n"
-            + "    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>\n"
-            + "  </listener>\n" + "  <listener>\n"
-            + "    <listener-class>org.apache.syncope.core.init.ThreadLocalCleanupListener</listener-class>\n"
-            + "  </listener>\n" + "    \n" + "  <servlet>\n" + "    <servlet-name>CXFServlet</servlet-name>\n"
-            + "    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>\n"
-            + "    <load-on-startup>1</load-on-startup> \n" + "  </servlet>\n" + "  <servlet-mapping>\n"
-            + "    <servlet-name>CXFServlet</servlet-name>\n" + "    <url-pattern>/rest/*</url-pattern>\n"
-            + "  </servlet-mapping>\n" + "  <servlet>\n" + "    <servlet-name>WADLServlet</servlet-name>\n"
-            + "    <servlet-class>org.apache.syncope.core.rest.WADLServlet</servlet-class>\n"
-            + "    <load-on-startup>2</load-on-startup> \n" + "  </servlet>\n" + "  <servlet-mapping>\n"
-            + "    <servlet-name>WADLServlet</servlet-name>\n" + "    <url-pattern>/rest/doc/*</url-pattern>\n"
-            + "  </servlet-mapping>\n" + "\n" + "  <filter>\n" + "    <filter-name>encodingFilter</filter-name>\n"
-            + "    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>\n"
-            + "    <init-param>\n" + "      <param-name>encoding</param-name>\n"
-            + "      <param-value>UTF-8</param-value>\n" + "    </init-param>\n" + "    <init-param>\n"
-            + "      <param-name>forceEncoding</param-name>\n" + "      <param-value>true</param-value>\n"
-            + "    </init-param>\n" + "  </filter>\n" + "  <filter>\n"
-            + "    <filter-name>springSecurityFilterChain</filter-name>\n"
-            + "    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>\n"
-            + "  </filter>\n" + "\n" + "  <filter-mapping>\n" + "    <filter-name>encodingFilter</filter-name>\n"
-            + "    <url-pattern>/*</url-pattern>\n" + "  </filter-mapping>\n" + "  <filter-mapping>\n"
-            + "    <filter-name>springSecurityFilterChain</filter-name>\n" + "    <url-pattern>/*</url-pattern>\n"
-            + "  </filter-mapping>\n" + "\n" + "  <login-config>\n" + "    <auth-method>CLIENT-CERT</auth-method>\n"
-            + "  </login-config>\n" + "    \n" + "  <!-- Uncomment this when using JNDI DataSource -->\n"
-            + "%s"
-            + "</web-app>\n";
-
-    private static final String withDataSource = "<!-- Uncomment this when using JNDI DataSource -->\n"
+    private static final String WITH_DATA_SOURCE = "<!-- Uncomment this when using JNDI DataSource -->\n"
             + "  <resource-ref>\n"
             + "    <res-ref-name>jdbc/syncopeDataSource</res-ref-name>\n"
             + "    <res-type>javax.sql.DataSource</res-type>\n"
             + "    <res-auth>Container</res-auth>\n"
-            + "  </resource-ref>\n" + "\n";
+            + "  </resource-ref>\n"
+            + "</web-app>";
 
-    private static final String withDataSourceForJBoss = "<!-- Uncomment this when using JNDI DataSource -->\n"
+    private static final String WITH_DATA_SOURCE_FOR_JBOSS = "<!-- Uncomment this when using JNDI DataSource -->\n"
             + "  <resource-ref>\n"
             + "    <res-ref-name>jdbc/syncopeDataSource</res-ref-name>\n"
             + "    <res-type>javax.sql.DataSource</res-type>\n"
             + "    <res-auth>Container</res-auth>\n"
             + "    <lookup-name>java:/syncopeDataSource</lookup-name>\n"
-            + "  </resource-ref>\n" + "\n";
+            + "  </resource-ref>\n"
+            + "</web-app>";
+
+    public static String withDataSource(final String content) {
+        return content.replace(PLACEHOLDER, WITH_DATA_SOURCE);
+    }
 
+    public static String withDataSourceForJBoss(final String content) {
+        return content.replace(PLACEHOLDER, WITH_DATA_SOURCE_FOR_JBOSS);
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/java/org/apache/syncope/installer/files/GlassfishCoreWebXml.java
----------------------------------------------------------------------
diff --git a/installer/src/main/java/org/apache/syncope/installer/files/GlassfishCoreWebXml.java b/installer/src/main/java/org/apache/syncope/installer/files/GlassfishCoreWebXml.java
index 0541209..9eadedd 100644
--- a/installer/src/main/java/org/apache/syncope/installer/files/GlassfishCoreWebXml.java
+++ b/installer/src/main/java/org/apache/syncope/installer/files/GlassfishCoreWebXml.java
@@ -20,38 +20,14 @@ package org.apache.syncope.installer.files;
 
 public class GlassfishCoreWebXml {
 
-    public static final String PATH = "/core/src/main/webapp/WEB-INF/glassfish-web.xml";
-
-    public static String withDataSource() {
-        return String.format(FILE, dataSource);
-    }
-
-    private final static String FILE = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<!--\n"
-            + "Licensed to the Apache Software Foundation (ASF) under one\n"
-            + "or more contributor license agreements.  See the NOTICE file\n"
-            + "distributed with this work for additional information\n"
-            + "regarding copyright ownership.  The ASF licenses this file\n"
-            + "to you under the Apache License, Version 2.0 (the\n"
-            + "\"License\"); you may not use this file except in compliance\n"
-            + "with the License.  You may obtain a copy of the License at\n" + "\n"
-            + "  http://www.apache.org/licenses/LICENSE-2.0\n" + "\n"
-            + "Unless required by applicable law or agreed to in writing,\n"
-            + "software distributed under the License is distributed on an\n"
-            + "\"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n"
-            + "KIND, either express or implied.  See the License for the\n"
-            + "specific language governing permissions and limitations\n" + "under the License.\n" + "\n" + "-->\n"
-            + "<!DOCTYPE glassfish-web-app PUBLIC \"-//GlassFish.org//DTD \n"
-            + "GlassFish Application Server 3.1 Servlet 3.0//EN\" \"http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd\">\n"
-            + "<glassfish-web-app>\n" + "  <context-root>/syncope</context-root>\n"
-            + "%s"
-            + "  <class-loader delegate=\"false\"/>\n" + "  <jsp-config>\n"
-            + "    <property name=\"httpMethods\" value=\"GET,POST,HEAD,PUT,DELETE\"/>\n" + "  </jsp-config>\n"
-            + "</glassfish-web-app>";
-
-    private static final String dataSource = "<!-- Uncomment this when using JNDI DataSource -->\n"
-            + "  <resource-ref>\n"
+    public static final String PLACEHOLDER = "  <!--<resource-ref>\n"
             + "    <res-ref-name>jdbc/syncopeDataSource</res-ref-name>\n"
             + "    <jndi-name>jdbc/syncopeDataSource</jndi-name>\n"
-            + "  </resource-ref>\n";
+            + "  </resource-ref>-->";
+
+    public static final String DATA_SOURCE = "  <resource-ref>\n"
+            + "    <res-ref-name>jdbc/syncopeDataSource</res-ref-name>\n"
+            + "    <jndi-name>jdbc/syncopeDataSource</jndi-name>\n" 
+            + "  </resource-ref>";
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/java/org/apache/syncope/installer/files/JBossDeploymentStructureXml.java
----------------------------------------------------------------------
diff --git a/installer/src/main/java/org/apache/syncope/installer/files/JBossDeploymentStructureXml.java b/installer/src/main/java/org/apache/syncope/installer/files/JBossDeploymentStructureXml.java
index 7a06b34..1d70e36 100644
--- a/installer/src/main/java/org/apache/syncope/installer/files/JBossDeploymentStructureXml.java
+++ b/installer/src/main/java/org/apache/syncope/installer/files/JBossDeploymentStructureXml.java
@@ -19,42 +19,10 @@
 package org.apache.syncope.installer.files;
 
 public class JBossDeploymentStructureXml {
+    
+    public static final String PLACEHOLDER = "<module name=\"org.apache.xalan\"/>";
 
-    public static final String PATH = "/core/src/main/webapp/WEB-INF/jboss-deployment-structure.xml";
-
-    public static final String FILE = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<!--\n"
-            + "Licensed to the Apache Software Foundation (ASF) under one\n"
-            + "or more contributor license agreements.  See the NOTICE file\n"
-            + "distributed with this work for additional information\n"
-            + "regarding copyright ownership.  The ASF licenses this file\n"
-            + "to you under the Apache License, Version 2.0 (the\n"
-            + "\"License\"); you may not use this file except in compliance\n"
-            + "with the License.  You may obtain a copy of the License at\n" + "\n"
-            + "       http://www.apache.org/licenses/LICENSE-2.0\n" + "\n"
-            + "Unless required by applicable law or agreed to in writing,\n"
-            + "software distributed under the License is distributed on an\n"
-            + "\"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n"
-            + "KIND, either express or implied.  See the License for the\n"
-            + "specific language governing permissions and limitations\n" + "under the License.\n" + "\n" + "-->\n"
-            + "<jboss-deployment-structure xmlns=\"urn:jboss:deployment-structure:1.2\">\n"
-            + "  <deployment>\n"
-            + "    <exclude-subsystems>\n" 
-            + "      <subsystem name=\"webservices\"/>\n" 
-            + "      <subsystem name=\"jaxrs\"/>\n" 
-            + "    </exclude-subsystems>"
-            + "    <dependencies>\n"
-            + "      <module name=\"org.apache.xalan\"/>\n"
-            + "      <module name=\"%s\"/>\n"
-            + "    </dependencies>\n"
-            + "    <exclusions>\n"
-            + "      <module name=\"org.hibernate\"/>\n"
-            + "      <module name=\"org.slf4j\"/>\n"
-            + "      <module name=\"org.slf4j.impl\"/>\n"
-            + "      <module name=\"javax.ws.rs.api\"/>\n"
-            + "      <module name=\"org.apache.cxf\"/>\n"
-            + "      <module name=\"org.apache.cxf.impl\"/>\n"
-            + "    </exclusions>\n"
-            + "  </deployment>\n"
-            + "</jboss-deployment-structure>";
+    public static final String JBOSSMODULE = "<module name=\"org.apache.xalan\"/>\n"
+            + "<module name=\"%s\"/>";
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/java/org/apache/syncope/installer/files/ParentPom.java
----------------------------------------------------------------------
diff --git a/installer/src/main/java/org/apache/syncope/installer/files/ParentPom.java b/installer/src/main/java/org/apache/syncope/installer/files/ParentPom.java
index edca681..49c05f3 100644
--- a/installer/src/main/java/org/apache/syncope/installer/files/ParentPom.java
+++ b/installer/src/main/java/org/apache/syncope/installer/files/ParentPom.java
@@ -19,176 +19,18 @@
 package org.apache.syncope.installer.files;
 
 public class ParentPom {
+    
+    public static final String PLACEHOLDER = "</project>";
 
-    public static final String PATH = "/pom.xml";
-
-    public static final String FILE = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!--\n"
-            + "Licensed to the Apache Software Foundation (ASF) under one\n"
-            + "or more contributor license agreements.  See the NOTICE file\n"
-            + "distributed with this work for additional information\n"
-            + "regarding copyright ownership.  The ASF licenses this file\n"
-            + "to you under the Apache License, Version 2.0 (the\n"
-            + "\"License\"); you may not use this file except in compliance\n"
-            + "with the License.  You may obtain a copy of the License at\n" + "\n"
-            + "  http://www.apache.org/licenses/LICENSE-2.0\n" + "\n"
-            + "Unless required by applicable law or agreed to in writing,\n"
-            + "software distributed under the License is distributed on an\n"
-            + "\"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n"
-            + "KIND, either express or implied.  See the License for the\n"
-            + "specific language governing permissions and limitations\n"
-            + "under the License.\n"
-            + "-->\n"
-            + "<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n"
-            + "         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
-            + "         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n"
-            + "  \n"
-            + "  <modelVersion>4.0.0</modelVersion>\n"
-            + "  \n"
-            + "  <parent>\n"
-            + "    <groupId>org.apache.syncope</groupId>\n"
-            + "    <artifactId>syncope</artifactId>\n"
-            + "    <version>%s</version>\n"
-            + "  </parent>\n"
-            + "  \n"
-            + "  <properties>\n"
-            + "    <syncope.version>%s</syncope.version>\n"
-            + "    <secretKey>ahsdgausygdausygduasygd</secretKey>\n"
-            + "    <anonymousKey>asdasdasdasd</anonymousKey>\n"
-            + "  </properties>\n"
-            + "  \n"
-            + "  <name>Apache Syncope sample project</name>\n"
-            + "  <groupId>%s</groupId>\n"
-            + "  <artifactId>%s</artifactId>\n"
-            + "  <version>1.0-SNAPSHOT</version>\n"
-            + "  <packaging>pom</packaging>\n"
-            + "  \n"
-            + "  <dependencyManagement>\n"
-            + "    <dependencies>\n"
-            + "      <dependency>\n"
-            + "        <groupId>org.apache.syncope</groupId>\n"
-            + "        <artifactId>syncope-common</artifactId>\n"
-            + "        <version>${syncope.version}</version>\n"
-            + "      </dependency> \n"
-            + "      \n"
-            + "      <dependency>\n"
-            + "        <groupId>org.apache.syncope</groupId>\n"
-            + "        <artifactId>syncope-common</artifactId>\n"
-            + "        <version>${syncope.version}</version>\n"
-            + "        <classifier>javadoc</classifier>\n"
-            + "      </dependency>\n"
-            + "      \n"
-            + "      <dependency>\n"
-            + "        <groupId>org.apache.syncope</groupId>\n"
-            + "        <artifactId>syncope-client</artifactId>\n"
-            + "        <version>${syncope.version}</version>\n"
-            + "      </dependency> \n"
-            + "      \n"
-            + "      <dependency>\n"
-            + "        <groupId>org.apache.syncope</groupId>\n"
-            + "        <artifactId>syncope-build-tools</artifactId>\n"
-            + "        <version>${syncope.version}</version>\n"
-            + "        <type>war</type>\n"
-            + "        <scope>test</scope>\n"
-            + "      </dependency> \n"
-            + "      \n"
-            + "      <dependency>\n"
-            + "        <groupId>org.apache.syncope</groupId>\n"
-            + "        <artifactId>syncope-core</artifactId>\n"
-            + "        <version>${syncope.version}</version>\n"
-            + "        <type>war</type>\n"
-            + "      </dependency> \n"
-            + "      <dependency>\n"
-            + "        <groupId>org.apache.syncope</groupId>\n"
-            + "        <artifactId>syncope-core</artifactId>\n"
-            + "        <version>${syncope.version}</version>\n"
-            + "        <classifier>classes</classifier>\n"
-            + "        <scope>provided</scope>\n"
-            + "      </dependency> \n"
-            + "     \n"
-            + "      <dependency>\n"
-            + "        <groupId>org.apache.syncope</groupId>\n"
-            + "        <artifactId>syncope-console</artifactId>\n"
-            + "        <version>${syncope.version}</version>\n"
-            + "        <type>war</type>\n"
-            + "      </dependency> \n"
-            + "      <dependency>\n"
-            + "        <groupId>org.apache.syncope</groupId>\n"
-            + "        <artifactId>syncope-console</artifactId>\n"
-            + "        <version>${syncope.version}</version>\n"
-            + "        <classifier>classes</classifier>\n"
-            + "        <scope>provided</scope>\n"
-            + "      </dependency> \n"
-            + "    </dependencies>\n"
-            + "  </dependencyManagement>\n"
-            + "    \n"
-            + "  <build>\n"
-            + "    \n"
-            + "    <pluginManagement>\n"
-            + "      <plugins>\n"
-            + "        <!-- Disable LICENSE / NOTICE inclusion: see SYNCOPE-84 -->\n"
-            + "        <plugin>\n"
-            + "          <groupId>org.apache.maven.plugins</groupId>\n"
-            + "          <artifactId>maven-war-plugin</artifactId>\n"
-            + "          <inherited>false</inherited>\n"
-            + "          <configuration>\n"
-            + "            <webResources>\n"
-            + "              <resource>\n"
-            + "                <directory>src/main/webapp</directory>\n"
-            + "                <includes>\n"
-            + "                  <include>**/*.jsp</include>\n"
-            + "                </includes>\n"
-            + "                <filtering>true</filtering>\n"
-            + "              </resource>\n"
-            + "            </webResources>\n"
-            + "          </configuration>\n"
-            + "        </plugin>\n"
-            + "      </plugins>\n"
-            + "    </pluginManagement>\n"
-            + "    \n"
-            + "    <!-- Disable legal check for generated projects: see SYNCOPE-84 -->\n"
-            + "    <plugins>\n"
-            + "      <plugin>\n"
-            + "        <groupId>org.codehaus.mojo</groupId>\n"
-            + "        <artifactId>ianal-maven-plugin</artifactId>\n"
-            + "        <inherited>true</inherited>\n"
-            + "        <executions>\n"
-            + "          <execution>            \n"
-            + "            <goals>\n"
-            + "              <goal>verify-legal-files</goal>\n"
-            + "            </goals>\n"
-            + "            <phase>none</phase>\n"
-            + "          </execution>\n"
-            + "        </executions>\n"
-            + "      </plugin>\n"
-            + "      <plugin>\n"
-            + "        <groupId>org.apache.rat</groupId>\n"
-            + "        <artifactId>apache-rat-plugin</artifactId>\n"
-            + "        <inherited>true</inherited>\n"
-            + "        <executions>\n"
-            + "          <execution>\n"
-            + "            <goals>\n"
-            + "              <goal>check</goal>\n"
-            + "            </goals>\n"
-            + "            <phase>none</phase>\n"
-            + "          </execution>\n"
-            + "        </executions>\n"
-            + "      </plugin>\n"
-            + "    </plugins>\n"
-            + "  </build>\n"
-            + "  \n"
-            + "  <modules>\n"
-            + "    <module>core</module>\n"
-            + "    <module>console</module>\n"
-            + "  </modules>\n"
-            + "  \n"
-            + "  <repositories>\n" 
-            + "  <repository>\n" 
+    public static final String REPOSITORY =
+            "  <repositories>\n"
+            + "  <repository>\n"
             + "    <id>ASF</id>\n"
-            + "    <url>https://repository.apache.org/content/repositories/snapshots/</url>\n" 
+            + "    <url>https://repository.apache.org/content/repositories/snapshots/</url>\n"
             + "    <snapshots>\n"
-            + "      <enabled>true</enabled>\n" 
-            + "    </snapshots>\n" 
-            + "  </repository>\n" 
+            + "      <enabled>true</enabled>\n"
+            + "    </snapshots>\n"
+            + "  </repository>\n"
             + "</repositories>\n"
             + "</project>\n";
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/java/org/apache/syncope/installer/files/PersistenceContextEMFactoryXml.java
----------------------------------------------------------------------
diff --git a/installer/src/main/java/org/apache/syncope/installer/files/PersistenceContextEMFactoryXml.java b/installer/src/main/java/org/apache/syncope/installer/files/PersistenceContextEMFactoryXml.java
index 0dd12c4..a64ea36 100644
--- a/installer/src/main/java/org/apache/syncope/installer/files/PersistenceContextEMFactoryXml.java
+++ b/installer/src/main/java/org/apache/syncope/installer/files/PersistenceContextEMFactoryXml.java
@@ -20,45 +20,12 @@ package org.apache.syncope.installer.files;
 
 public class PersistenceContextEMFactoryXml {
 
-    public static final String PATH = "/core/src/main/resources/persistenceContextEMFactory.xml";
+    public static final String PLACEHOLDER = "<entry key=\"openjpa.MetaDataFactory\"\n"
+            + "               value=\"jpa(URLs=vfs:${project.build.directory}/cargo/configurations/wildfly8x/"
+            + "deployments/${project.build.finalName}.war/WEB-INF/classes/, Resources=META-INF/orm.xml)\"/>";
+
+    public static final String JBOSS =
+            "<entry key=\"openjpa.MetaDataFactory\" value=\"jpa(URLs=vfs:/content/${project.build.finalName}.war/"
+            + "WEB-INF/classes/, Resources=META-INF/orm.xml)\"/>";
 
-    public static final String FILE = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<!--\n"
-            + "Licensed to the Apache Software Foundation (ASF) under one\n"
-            + "or more contributor license agreements.  See the NOTICE file\n"
-            + "distributed with this work for additional information\n"
-            + "regarding copyright ownership.  The ASF licenses this file\n"
-            + "to you under the Apache License, Version 2.0 (the\n"
-            + "\"License\"); you may not use this file except in compliance\n"
-            + "with the License.  You may obtain a copy of the License at\n" + "\n"
-            + "  http://www.apache.org/licenses/LICENSE-2.0\n" + "\n"
-            + "Unless required by applicable law or agreed to in writing,\n"
-            + "software distributed under the License is distributed on an\n"
-            + "\"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n"
-            + "KIND, either express or implied.  See the License for the\n"
-            + "specific language governing permissions and limitations\n" + "under the License.\n" + "-->\n"
-            + "<beans xmlns=\"http://www.springframework.org/schema/beans\"\n"
-            + "       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
-            + "       xsi:schemaLocation=\"http://www.springframework.org/schema/beans\n"
-            + "       http://www.springframework.org/schema/beans/spring-beans.xsd\">\n" + "\n"
-            + "  <bean id=\"entityManagerFactory\"\n"
-            + "        class=\"org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean\">\n"
-            + "    <property name=\"persistenceXmlLocation\" value=\"classpath*:META-INF/spring-persistence.xml\"/>\n"
-            + "    <property name=\"persistenceUnitName\" value=\"syncopePersistenceUnit\"/>\n"
-            + "    <property name=\"dataSource\" ref=\"dataSource\"/>\n" + "    <property name=\"jpaVendorAdapter\">\n"
-            + "      <bean class=\"org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter\">\n"
-            + "        <property name=\"showSql\" value=\"false\"/>\n"
-            + "        <property name=\"generateDdl\" value=\"true\"/>\n"
-            + "        <property name=\"databasePlatform\" value=\"${jpa.dialect}\"/>\n" + "      </bean>\n"
-            + "    </property>\n" + "    <property name=\"jpaPropertyMap\">\n" + "      <map>\n"
-            + "        <!--<entry key=\"openjpa.Log\" value=\"SQL=TRACE\"/>\n"
-            + "        <entry key=\"openjpa.ConnectionFactoryProperties\" \n"
-            + "               value=\"PrintParameters=true, PrettyPrint=true, PrettyPrintLineLength=80\"/>-->\n"
-            + "                \n" + "        <entry key=\"openjpa.NontransactionalWrite\" value=\"false\"/>\n"
-            + "        <entry key=\"openjpa.AutoDetach\" value=\"close, commit, nontx-read, rollback\"/>\n" + "\n"
-            + "        <entry key=\"openjpa.jdbc.SchemaFactory\" value=\"native(ForeignKeys=true)\"/>\n"
-            + "        <entry key=\"openjpa.jdbc.MappingDefaults\" value=\"ForeignKeyDeleteAction=restrict, JoinForeignKeyDeleteAction=restrict\"/>\n"
-            + "                \n" + "        <entry key=\"openjpa.DataCache\" value=\"true\"/>\n"
-            + "        <entry key=\"openjpa.QueryCache\" value=\"true\"/>\n"
-            + "        <entry key=\"openjpa.RemoteCommitProvider\" value=\"sjvm\"/>\n" + "      </map>\n"
-            + "    </property>\n" + "  </bean>\n" + "\n" + "</beans>\n";
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/java/org/apache/syncope/installer/files/PersistenceProperties.java
----------------------------------------------------------------------
diff --git a/installer/src/main/java/org/apache/syncope/installer/files/PersistenceProperties.java b/installer/src/main/java/org/apache/syncope/installer/files/PersistenceProperties.java
index c27ac35..cba0b61 100644
--- a/installer/src/main/java/org/apache/syncope/installer/files/PersistenceProperties.java
+++ b/installer/src/main/java/org/apache/syncope/installer/files/PersistenceProperties.java
@@ -20,8 +20,6 @@ package org.apache.syncope.installer.files;
 
 public class PersistenceProperties {
 
-    public static final String PATH = "/core/src/main/resources/persistence.properties";
-
     public static final String HEADER = "# Licensed to the Apache Software Foundation (ASF) under one\n"
             + "# or more contributor license agreements.  See the NOTICE file\n"
             + "# distributed with this work for additional information\n"
@@ -59,28 +57,31 @@ public class PersistenceProperties {
             + "audit.sql=audit.sql\n"
             + "database.schema=\n";
 
-    public static final String ORACLE = ""
-            + "jpa.driverClassName=oracle.jdbc.OracleDriver\n"
+    public static final String ORACLE = "jpa.driverClassName=oracle.jdbc.OracleDriver\n"
             + "jpa.url=%s\n"
             + "jpa.username=%s\n"
             + "jpa.password=%s\n"
             + "jpa.dialect=org.apache.openjpa.jdbc.sql.OracleDictionary\n"
-            + "jpa.pool.validationQuery=SELECT 1\n"
+            + "jpa.pool.validationQuery=SELECT 1 FROM DUAL\n"
+            + "#note: other connection pool settings can also be configured here, see persistenceContext.xml\n"
             + "quartz.jobstore=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate\n"
+            + "quartz.scheduler.idleWaitTime=5000\n"
             + "quartz.sql=tables_oracle.sql\n"
-            + "audit.sql=audit.sql\n"
+            + "audit.sql=audit_oracle.sql\n"
             + "database.schema=%s\n";
 
-    public static final String SQLSERVER = ""
-            + "jpa.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver\n"
+    public static final String SQLSERVER = "jpa.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver\n"
             + "jpa.url=%s\n"
             + "jpa.username=%s\n"
             + "jpa.password=%s\n"
-            + "jpa.dialect=org.apache.openjpa.jdbc.sql.SQLServerDictionary\n"
-            + "quartz.jobstore=org.quartz.impl.jdbcjobstore.MSSQLDelegate\n"
-            + "quartz.sql=tables_sqlServer.sql\n"
-            + "audit.sql=audit.sql\n"
-            + "database.schema=\n";
+            + "jpa.dialect=org.apache.openjpa.jdbc.sql.SQLServerDictionary\n" 
+            + "jpa.pool.validationQuery=SELECT 1\n"
+            + "#note: other connection pool settings can also be configured here, see persistenceContext.xml\n"
+            + "quartz.jobstore=org.quartz.impl.jdbcjobstore.MSSQLDelegate\n" 
+            + "quartz.scheduler.idleWaitTime=5000\n"
+            + "quartz.sql=tables_sqlServer.sql\n" 
+            + "audit.sql=audit_sqlserver.sql\n" 
+            + "database.schema=";
 
     public static final String QUARTZ_INNO_DB = "quartz.sql=tables_mysql_innodb.sql";
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/java/org/apache/syncope/installer/processes/ArchetypeProcess.java
----------------------------------------------------------------------
diff --git a/installer/src/main/java/org/apache/syncope/installer/processes/ArchetypeProcess.java b/installer/src/main/java/org/apache/syncope/installer/processes/ArchetypeProcess.java
index 45569e7..0c7bdea 100644
--- a/installer/src/main/java/org/apache/syncope/installer/processes/ArchetypeProcess.java
+++ b/installer/src/main/java/org/apache/syncope/installer/processes/ArchetypeProcess.java
@@ -22,16 +22,15 @@ import org.apache.syncope.installer.utilities.FileSystemUtils;
 import com.izforge.izpack.panels.process.AbstractUIProcessHandler;
 import java.io.File;
 import java.io.IOException;
+import java.util.Properties;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.TransformerException;
-import org.apache.syncope.installer.files.ModelerPom;
-import org.apache.syncope.installer.files.ModelerTokenValueMap;
 import org.apache.syncope.installer.files.ParentPom;
 import org.apache.syncope.installer.utilities.InstallLog;
 import org.apache.syncope.installer.utilities.MavenUtils;
 import org.xml.sax.SAXException;
 
-public class ArchetypeProcess {
+public class ArchetypeProcess extends BaseProcess {
 
     public void run(final AbstractUIProcessHandler handler, final String[] args) {
         final String installPath = args[0];
@@ -52,6 +51,8 @@ public class ArchetypeProcess {
         final String proxyUser = args[15];
         final String proxyPwd = args[16];
         final boolean mavenProxyAutoconf = Boolean.valueOf(args[17]);
+        
+        setSyncopeInstallDir(installPath, artifactId);
 
         final FileSystemUtils fileSystemUtils = new FileSystemUtils(handler);
         fileSystemUtils.createDirectory(installPath);
@@ -97,21 +98,37 @@ public class ArchetypeProcess {
         handler.logOutput("########################## IMPORTANT ##########################", true);
         mavenUtils.archetypeGenerate(
                 syncopeVersion, groupId, artifactId, secretKey, anonymousKey, installPath, customMavenProxySettings);
-        
+
         if (syncopeVersion.contains("SNAPSHOT")) {
-            fileSystemUtils.writeToFile(new File(installPath + "/" + artifactId + ParentPom.PATH),
-                    String.format(ParentPom.FILE, syncopeVersion, syncopeVersion, groupId, artifactId));
+            final File pomFile =
+                    new File(syncopeInstallDir + properties.getProperty("pomFile"));
+            String contentPomFile = fileSystemUtils.readFile(pomFile);
+            fileSystemUtils.writeToFile(pomFile, contentPomFile.replace(ParentPom.PLACEHOLDER, ParentPom.REPOSITORY));
         }
-        
+
         fileSystemUtils.createDirectory(confDirectory);
         fileSystemUtils.createDirectory(logsDirectory);
         fileSystemUtils.createDirectory(bundlesDirectory);
         fileSystemUtils.createDirectory(modelerDirectory);
-        fileSystemUtils.writeToFile(new File(modelerDirectory + ModelerPom.PATH),
-                String.format(ModelerPom.FILE, modelerDirectory, modelerDirectory));
-        fileSystemUtils.writeToFile(new File(modelerDirectory + ModelerTokenValueMap.PATH), ModelerTokenValueMap.FILE);
-        mavenUtils.mvnCleanPackage(modelerDirectory, customMavenProxySettings);
+        
+        fileSystemUtils.copyFileFromResources("/" + properties.getProperty("modelerPomFile"),
+                modelerDirectory + "/" + properties.getProperty("pomFile"), handler);
+
+        fileSystemUtils.copyFile(
+                syncopeInstallDir
+                + properties.getProperty("consoleResDirectory")
+                + "/" + properties.getProperty("tokenValueMapFile"),
+                modelerDirectory + "/" + properties.getProperty("tokenValueMapFile"));
+
+        final Properties modelerProperties = new Properties();
+        modelerProperties.setProperty("modeler.directory", modelerDirectory);
+        mavenUtils.mvnCleanPackageWithProperties(modelerDirectory, modelerProperties, customMavenProxySettings);
+
+        final Properties syncopeProperties = new Properties();
+        syncopeProperties.setProperty("conf.directory", confDirectory);
+        syncopeProperties.setProperty("log.directory", logsDirectory);
+        syncopeProperties.setProperty("bundles.directory", bundlesDirectory);
         mavenUtils.mvnCleanPackageWithProperties(
-                installPath + "/" + artifactId, confDirectory, logsDirectory, bundlesDirectory, customMavenProxySettings);
+                installPath + "/" + artifactId, syncopeProperties, customMavenProxySettings);
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/java/org/apache/syncope/installer/processes/BaseProcess.java
----------------------------------------------------------------------
diff --git a/installer/src/main/java/org/apache/syncope/installer/processes/BaseProcess.java b/installer/src/main/java/org/apache/syncope/installer/processes/BaseProcess.java
new file mode 100644
index 0000000..2058c12
--- /dev/null
+++ b/installer/src/main/java/org/apache/syncope/installer/processes/BaseProcess.java
@@ -0,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.installer.processes;
+
+import static org.apache.syncope.installer.processes.ArchetypeProcess.properties;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+import org.apache.commons.io.IOUtils;
+
+public class BaseProcess {
+
+    protected final static Properties properties = new Properties();
+
+    protected String syncopeInstallDir;
+
+    private static InputStream is = null;
+
+    static {
+        try {
+            is = BaseProcess.class.getResourceAsStream("/configuration.properties");
+            properties.load(is);
+        } catch (final IOException e) {
+        } finally {
+            IOUtils.closeQuietly(is);
+        }
+    }
+
+    protected void setSyncopeInstallDir(final String installPath, final String artifactId) {
+        final StringBuilder path = new StringBuilder();
+        path.append(installPath);
+        path.append("/");
+        path.append(artifactId);
+        path.append("/");
+        syncopeInstallDir = path.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/java/org/apache/syncope/installer/processes/ContainerProcess.java
----------------------------------------------------------------------
diff --git a/installer/src/main/java/org/apache/syncope/installer/processes/ContainerProcess.java b/installer/src/main/java/org/apache/syncope/installer/processes/ContainerProcess.java
index 62cd6d4..6b99918 100644
--- a/installer/src/main/java/org/apache/syncope/installer/processes/ContainerProcess.java
+++ b/installer/src/main/java/org/apache/syncope/installer/processes/ContainerProcess.java
@@ -22,21 +22,31 @@ import org.apache.syncope.installer.utilities.FileSystemUtils;
 import com.izforge.izpack.panels.process.AbstractUIProcessHandler;
 import java.io.File;
 import java.io.IOException;
+import java.util.Properties;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.TransformerException;
 import org.apache.syncope.installer.containers.Glassfish;
 import org.apache.syncope.installer.containers.Tomcat;
 import org.apache.syncope.installer.containers.jboss.JBoss;
 import org.apache.syncope.installer.enums.Containers;
+import org.apache.syncope.installer.files.ConsoleProperties;
 import org.apache.syncope.installer.files.GlassfishCoreWebXml;
 import org.apache.syncope.installer.files.JBossDeploymentStructureXml;
-import org.apache.syncope.installer.files.PersistenceContextEMFactoryXml;
 import org.apache.syncope.installer.files.CoreWebXml;
+import org.apache.syncope.installer.files.PersistenceContextEMFactoryXml;
 import org.apache.syncope.installer.utilities.InstallLog;
 import org.apache.syncope.installer.utilities.MavenUtils;
 import org.xml.sax.SAXException;
 
-public class ContainerProcess {
+public class ContainerProcess extends BaseProcess {
+
+    private final static String HTTP = "http";
+
+    private final static String HTTPS = "https";
+
+    private final static String DEFAULT_HOST = "localhost";
+
+    private final static String DEFAULT_PORT = "8080";
 
     private String installPath;
 
@@ -56,6 +66,12 @@ public class ContainerProcess {
 
     private String glassfishDir;
 
+    private boolean glassfishSsl;
+
+    private String glassfishHost;
+
+    private String glassfishPort;
+
     private String confDirectory;
 
     private String logsDirectory;
@@ -76,6 +92,8 @@ public class ContainerProcess {
 
     private String jbossAdminPassword;
 
+    private String jbossManagementPort;
+
     private boolean isProxyEnabled;
 
     private String proxyHost;
@@ -99,49 +117,104 @@ public class ContainerProcess {
         tomcatPort = args[6];
         tomcatUser = args[7];
         tomcatPassword = args[8];
-        glassfishDir = args[9];
-        confDirectory = args[10];
-        logsDirectory = args[11];
-        bundlesDirectory = args[12];
-        withDataSource = Boolean.valueOf(args[13]);
-        jbossSsl = Boolean.valueOf(args[14]);
-        jbossHost = args[15];
-        jbossPort = args[16];
-        jbossJdbcModuleName = args[17];
-        jbossAdminUsername = args[18];
-        jbossAdminPassword = args[19];
-        isProxyEnabled = Boolean.valueOf(args[20]);
-        proxyHost = args[21];
-        proxyPort = args[22];
-        proxyUser = args[23];
-        proxyPwd = args[24];
-        mavenProxyAutoconf = Boolean.valueOf(args[25]);
+        glassfishSsl = Boolean.valueOf(args[9]);
+        glassfishHost = args[10];
+        glassfishPort = args[11];
+        glassfishDir = args[12];
+        confDirectory = args[13];
+        logsDirectory = args[14];
+        bundlesDirectory = args[15];
+        withDataSource = Boolean.valueOf(args[16]);
+        jbossSsl = Boolean.valueOf(args[17]);
+        jbossHost = args[18];
+        jbossPort = args[19];
+        jbossJdbcModuleName = args[20];
+        jbossAdminUsername = args[21];
+        jbossAdminPassword = args[22];
+        jbossManagementPort = args[23];
+        isProxyEnabled = Boolean.valueOf(args[24]);
+        proxyHost = args[25];
+        proxyPort = args[26];
+        proxyUser = args[27];
+        proxyPwd = args[28];
+        mavenProxyAutoconf = Boolean.valueOf(args[28]);
 
         final FileSystemUtils fileSystemUtils = new FileSystemUtils(handler);
-
+        
         handler.logOutput("Configure web.xml file according to " + selectedContainer + " properties", true);
         InstallLog.getInstance().info("Configure web.xml file according to " + selectedContainer + " properties");
-
+        
+        setSyncopeInstallDir(installPath, artifactId);
+                
         if (withDataSource) {
-            fileSystemUtils.writeToFile(new File(installPath + "/" + artifactId + CoreWebXml.PATH), CoreWebXml.
-                    withDataSource());
+            final File coreWebXmlFile =
+                    new File(syncopeInstallDir + properties.getProperty("coreWebXmlFile"));
+            final String contentCoreWebXmlFile = fileSystemUtils.readFile(coreWebXmlFile);
+
             switch (selectedContainer) {
+                case TOMCAT:
+                    fileSystemUtils.writeToFile(coreWebXmlFile, CoreWebXml.withDataSource(contentCoreWebXmlFile));
+                    break;
                 case JBOSS:
-                    fileSystemUtils.writeToFile(new File(installPath + "/" + artifactId + CoreWebXml.PATH),
-                            CoreWebXml.withDataSourceForJBoss());
-                    fileSystemUtils.writeToFile(new File(installPath + "/" + artifactId
-                            + PersistenceContextEMFactoryXml.PATH), PersistenceContextEMFactoryXml.FILE);
-                    fileSystemUtils.writeToFile(new File(installPath + "/" + artifactId
-                            + JBossDeploymentStructureXml.PATH),
-                            String.format(JBossDeploymentStructureXml.FILE, jbossJdbcModuleName));
+                    fileSystemUtils.
+                            writeToFile(coreWebXmlFile, CoreWebXml.withDataSourceForJBoss(contentCoreWebXmlFile));
+                    final File jbossDeploymentStructureFile =
+                            new File(syncopeInstallDir + properties.getProperty("jBossDeploymentStructureXmlFile"));
+                    final String contentJbossDeploymentStructureFile =
+                            fileSystemUtils.readFile(jbossDeploymentStructureFile);
+                    fileSystemUtils.writeToFile(
+                            jbossDeploymentStructureFile,
+                            contentJbossDeploymentStructureFile.replace(
+                                    JBossDeploymentStructureXml.PLACEHOLDER,
+                                    String.format(JBossDeploymentStructureXml.JBOSSMODULE, jbossJdbcModuleName)));
                     break;
                 case GLASSFISH:
-                    fileSystemUtils.writeToFile(new File(installPath + "/" + artifactId + GlassfishCoreWebXml.PATH),
-                            GlassfishCoreWebXml.withDataSource());
+                    final File glassfishCoreWebXmlFile =
+                            new File(syncopeInstallDir + properties.getProperty("glassfishCoreWebXmlFile"));
+                    final String contentGlassfishWebXmlFile = fileSystemUtils.readFile(glassfishCoreWebXmlFile);
+                    fileSystemUtils.writeToFile(glassfishCoreWebXmlFile,
+                            contentGlassfishWebXmlFile.replace(GlassfishCoreWebXml.PLACEHOLDER,
+                                    GlassfishCoreWebXml.DATA_SOURCE));
                     break;
             }
         }
 
+        final File consolePropertiesFile =
+                new File(syncopeInstallDir
+                        + properties.getProperty("consoleResDirectory")
+                        + "/" + properties.getProperty("consolePropertiesFile"));
+        final String contentConsolePropertiesFile = fileSystemUtils.readFile(consolePropertiesFile);
+
+        final String scheme;
+        final String host;
+        final String port;
+        switch (selectedContainer) {
+            case TOMCAT:
+                scheme = tomcatSsl ? HTTPS : HTTP;
+                host = tomcatHost;
+                port = tomcatPort;
+                break;
+            case JBOSS:
+                scheme = jbossSsl ? HTTPS : HTTP;
+                host = jbossHost;
+                port = jbossPort;
+                persistenceContextEMFactory(fileSystemUtils, handler);
+                break;
+            case GLASSFISH:
+                scheme = glassfishSsl ? HTTPS : HTTP;
+                host = glassfishHost;
+                port = glassfishPort;
+                break;
+            default:
+                scheme = HTTP;
+                host = DEFAULT_HOST;
+                port = DEFAULT_PORT;
+        }
+
+        fileSystemUtils.writeToFile(consolePropertiesFile,
+                contentConsolePropertiesFile.replace(ConsoleProperties.PLACEHOLDER,
+                        String.format(ConsoleProperties.CONSOLE, scheme, host, port)));
+
         final MavenUtils mavenUtils = new MavenUtils(mavenDir, handler);
         File customMavenProxySettings = null;
         try {
@@ -178,8 +251,14 @@ public class ContainerProcess {
             InstallLog.getInstance().error(messageError.append(ex.getMessage() == null ? "" : ex.getMessage()).
                     toString());
         }
-        mavenUtils.mvnCleanPackageWithProperties(installPath + "/" + artifactId, confDirectory, logsDirectory, bundlesDirectory,
-                customMavenProxySettings);
+
+        final Properties mvnProperties = new Properties();
+        mvnProperties.setProperty("conf.directory", confDirectory);
+        mvnProperties.setProperty("log.directory", logsDirectory);
+        mvnProperties.setProperty("bundles.directory", bundlesDirectory);
+        mavenUtils.mvnCleanPackageWithProperties(
+                installPath + "/" + artifactId, mvnProperties, customMavenProxySettings);
+
         if (isProxyEnabled && mavenProxyAutoconf) {
             FileSystemUtils.delete(customMavenProxySettings);
         }
@@ -187,7 +266,8 @@ public class ContainerProcess {
         switch (selectedContainer) {
             case TOMCAT:
                 final Tomcat tomcat = new Tomcat(
-                        tomcatSsl, tomcatHost, tomcatPort, installPath, artifactId, tomcatUser, tomcatPassword, handler);
+                        tomcatSsl, tomcatHost, tomcatPort, installPath, artifactId, tomcatUser, tomcatPassword,
+                        handler);
                 boolean deployCoreResult = tomcat.deployCore();
                 if (deployCoreResult) {
                     handler.logOutput("Core successfully deployed ", true);
@@ -210,7 +290,7 @@ public class ContainerProcess {
                 break;
             case JBOSS:
                 final JBoss jBoss = new JBoss(
-                        jbossSsl, jbossHost, jbossPort, jbossAdminUsername,
+                        jbossSsl, jbossHost, jbossManagementPort, jbossAdminUsername,
                         jbossAdminPassword, installPath, artifactId, handler);
 
                 boolean deployCoreJboss = jBoss.deployCore();
@@ -239,10 +319,25 @@ public class ContainerProcess {
 
                 final Glassfish glassfish = new Glassfish(installPath, artifactId);
 
-                fileSystemUtils.exec("sh " + glassfishDir + Glassfish.DEPLOY_COMMAND + glassfish.deployCore(), null);
-                fileSystemUtils.exec("sh " + glassfishDir + Glassfish.DEPLOY_COMMAND + glassfish.deployConsole(), null);
+                fileSystemUtils.exec("sh " + glassfishDir
+                        + Glassfish.DEPLOY_COMMAND + glassfish.deployCore(), null);
+                fileSystemUtils.exec("sh " + glassfishDir
+                        + Glassfish.DEPLOY_COMMAND + glassfish.deployConsole(), null);
                 break;
         }
     }
 
+    private void persistenceContextEMFactory(
+            final FileSystemUtils fileSystemUtils, final AbstractUIProcessHandler handler) {
+        fileSystemUtils.copyFileFromResources("/jboss/persistenceContextEMFactory.xml",
+                syncopeInstallDir
+                + properties.getProperty("persistenceContextEMFactoryFile"), handler);
+        final File persistenceContextEMFactoryFile = new File(
+                syncopeInstallDir + properties.getProperty("persistenceContextEMFactoryFile"));
+        final String contentPersistenceContextEMFactory = fileSystemUtils.readFile(persistenceContextEMFactoryFile);
+        fileSystemUtils.writeToFile(
+                persistenceContextEMFactoryFile,
+                contentPersistenceContextEMFactory.replace(PersistenceContextEMFactoryXml.PLACEHOLDER,
+                        PersistenceContextEMFactoryXml.JBOSS));
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/java/org/apache/syncope/installer/processes/PersistenceProcess.java
----------------------------------------------------------------------
diff --git a/installer/src/main/java/org/apache/syncope/installer/processes/PersistenceProcess.java b/installer/src/main/java/org/apache/syncope/installer/processes/PersistenceProcess.java
index 983e3e8..33356f6 100644
--- a/installer/src/main/java/org/apache/syncope/installer/processes/PersistenceProcess.java
+++ b/installer/src/main/java/org/apache/syncope/installer/processes/PersistenceProcess.java
@@ -22,11 +22,10 @@ import org.apache.syncope.installer.utilities.FileSystemUtils;
 import com.izforge.izpack.panels.process.AbstractUIProcessHandler;
 import java.io.File;
 import org.apache.syncope.installer.enums.DBs;
-import org.apache.syncope.installer.files.OrmXml;
 import org.apache.syncope.installer.files.PersistenceProperties;
 import org.apache.syncope.installer.utilities.InstallLog;
 
-public class PersistenceProcess {
+public class PersistenceProcess extends BaseProcess {
 
     private String installPath;
 
@@ -56,8 +55,8 @@ public class PersistenceProcess {
         oracleTableSpace = args[7];
 
         final FileSystemUtils fileSystemUtils = new FileSystemUtils(handler);
-
         final StringBuilder persistenceProperties = new StringBuilder(PersistenceProperties.HEADER);
+        setSyncopeInstallDir(installPath, artifactId);
 
         handler.logOutput("Configure persistence file according to " + dbSelected + " properties", true);
         InstallLog.getInstance().info("Configure persistence file according to " + dbSelected + " properties");
@@ -80,24 +79,22 @@ public class PersistenceProcess {
                 persistenceProperties.append(String.format(
                         PersistenceProperties.ORACLE, persistenceUrl, persistenceUser, persistencePassword,
                         oracleTableSpace));
-                writeOrmFile(fileSystemUtils, OrmXml.ORACLE_ORM);
+                fileSystemUtils.copyFileFromResources("/META-INF/orm.xml.oracle",
+                        syncopeInstallDir + properties.getProperty("coreMetaInfDirectory")
+                        + "/" + properties.getProperty("ormXmlFile"), handler);
                 break;
             case SQLSERVER:
                 persistenceProperties.append(String.format(
                         PersistenceProperties.SQLSERVER, persistenceUrl, persistenceUser, persistencePassword));
-                writeOrmFile(fileSystemUtils, OrmXml.SQLSERVER_ORM);
+                fileSystemUtils.copyFileFromResources("/META-INF/orm.xml.sqlserver",
+                        syncopeInstallDir
+                        + properties.getProperty("coreMetaInfDirectory")
+                        + "/" + properties.getProperty("ormXmlFile"), handler);
                 break;
         }
 
         fileSystemUtils.writeToFile(new File(
-                installPath + "/" + artifactId + PersistenceProperties.PATH), persistenceProperties.toString());
-
-    }
-
-    private void writeOrmFile(final FileSystemUtils fileSystemUtils, final String content) {
-        fileSystemUtils.createDirectory(
-                installPath + File.separator + artifactId + OrmXml.PATH_DIR);
-        fileSystemUtils.writeToFile(
-                new File(installPath + File.separator + artifactId + OrmXml.PATH_COMPLETE), content);
+                syncopeInstallDir + properties.getProperty("persistencePropertiesFile")),
+                persistenceProperties.toString());
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/java/org/apache/syncope/installer/utilities/FileSystemUtils.java
----------------------------------------------------------------------
diff --git a/installer/src/main/java/org/apache/syncope/installer/utilities/FileSystemUtils.java b/installer/src/main/java/org/apache/syncope/installer/utilities/FileSystemUtils.java
index aea1c95..4381c1e 100644
--- a/installer/src/main/java/org/apache/syncope/installer/utilities/FileSystemUtils.java
+++ b/installer/src/main/java/org/apache/syncope/installer/utilities/FileSystemUtils.java
@@ -29,6 +29,11 @@ import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
+import java.net.URL;
+import java.nio.file.CopyOption;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
@@ -54,6 +59,21 @@ public class FileSystemUtils {
         }
     }
 
+    public void copyFile(final String sourceFilePath, final String targetFilePath) {
+        try {
+            final CopyOption[] options = new CopyOption[] {
+                StandardCopyOption.REPLACE_EXISTING,
+                StandardCopyOption.COPY_ATTRIBUTES
+            };
+            Files.copy(Paths.get(sourceFilePath), Paths.get(targetFilePath), options);
+        } catch (final IOException ex) {
+            final String errorMessage =
+                    "Error copy file " + sourceFilePath + " to " + targetFilePath;
+            handler.emitError(errorMessage, errorMessage);
+            InstallLog.getInstance().error(errorMessage);
+        }
+    }
+
     public void exec(final String cmd, final String path) {
         try {
             handler.logOutput("Executing " + cmd, true);
@@ -96,6 +116,18 @@ public class FileSystemUtils {
         }
     }
 
+    public String readFile(final File file) {
+        String content = "";
+        try {
+            content = FileUtils.readFileToString(file);
+        } catch (IOException ex) {
+            final String errorMessage = "Error reading file " + file.getAbsolutePath() + ": " + ex.getMessage();
+            handler.emitError(errorMessage, errorMessage);
+            InstallLog.getInstance().error(errorMessage);
+        }
+        return content;
+    }
+
     public void appendToFile(final File file, final String content) {
         try {
             if (!file.exists()) {
@@ -131,4 +163,17 @@ public class FileSystemUtils {
     public static void delete(final File file) {
         FileUtils.deleteQuietly(file);
     }
+
+    public void copyFileFromResources(final String filePath,
+            final String destination, final AbstractUIProcessHandler handler) {
+        try {
+            final URL url = getClass().getResource(filePath);
+            final File dest = new File(destination);
+            FileUtils.copyURLToFile(url, dest);
+        } catch (IOException ex) {
+            final String errorMessage = "Error copy file " + filePath;
+            handler.emitError(errorMessage, errorMessage);
+            InstallLog.getInstance().error(errorMessage);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/java/org/apache/syncope/installer/utilities/MavenUtils.java
----------------------------------------------------------------------
diff --git a/installer/src/main/java/org/apache/syncope/installer/utilities/MavenUtils.java b/installer/src/main/java/org/apache/syncope/installer/utilities/MavenUtils.java
index e842ea7..f39d4b4 100644
--- a/installer/src/main/java/org/apache/syncope/installer/utilities/MavenUtils.java
+++ b/installer/src/main/java/org/apache/syncope/installer/utilities/MavenUtils.java
@@ -65,8 +65,8 @@ public class MavenUtils {
         final InvocationRequest request = new DefaultInvocationRequest();
         request.setGoals(Collections.singletonList("archetype:generate"));
         request.setInteractive(false);
-        final Properties properties
-                = archetypeProperties(archetypeVersion, groupId, artifactId, secretKey, anonymousKey);
+        final Properties properties =
+                archetypeProperties(archetypeVersion, groupId, artifactId, secretKey, anonymousKey);
         request.setProperties(properties);
         if (customSettingsFile != null && FileUtils.sizeOf(customSettingsFile) > 0) {
             request.setUserSettingsFile(customSettingsFile);
@@ -94,24 +94,8 @@ public class MavenUtils {
         return properties;
     }
 
-    public void mvnCleanPackage(final String path, final File customSettingsFile) {
+    public void mvnCleanPackageWithProperties(final String path, final Properties properties, final File customSettingsFile) {
         final InvocationRequest request = new DefaultInvocationRequest();
-        if (customSettingsFile != null && FileUtils.sizeOf(customSettingsFile) > 0) {
-            request.setUserSettingsFile(customSettingsFile);
-        }
-        final List<String> mavenGoals = new ArrayList<String>();
-        mavenGoals.add("clean");
-        mavenGoals.add("package");
-        request.setGoals(mavenGoals);
-        logToHandler(request.getGoals(), new Properties());
-        logToFile(request.getGoals(), new Properties());
-        invoke(request, path);
-    }
-
-    public void mvnCleanPackageWithProperties(final String path, final String confDirectory,
-            final String logDirectory, final String bundlesDirectory, final File customSettingsFile) {
-        final InvocationRequest request = new DefaultInvocationRequest();
-        final Properties properties = packageProperties(confDirectory, logDirectory, bundlesDirectory);
         request.setProperties(properties);
         if (customSettingsFile != null && FileUtils.sizeOf(customSettingsFile) > 0) {
             request.setUserSettingsFile(customSettingsFile);
@@ -149,15 +133,6 @@ public class MavenUtils {
         }
     }
 
-    private Properties packageProperties(final String confDirectory, final String logDirectory,
-            final String bundlesDirectory) {
-        final Properties properties = new Properties();
-        properties.setProperty("conf.directory", confDirectory);
-        properties.setProperty("log.directory", logDirectory);
-        properties.setProperty("bundles.directory", bundlesDirectory);
-        return properties;
-    }
-
     private InvocationResult invoke(final InvocationRequest request, final String path) {
         InvocationResult result = null;
         final Invoker invoker = new DefaultInvoker();

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/resources/configuration.properties
----------------------------------------------------------------------
diff --git a/installer/src/main/resources/configuration.properties b/installer/src/main/resources/configuration.properties
new file mode 100644
index 0000000..e06fe57
--- /dev/null
+++ b/installer/src/main/resources/configuration.properties
@@ -0,0 +1,31 @@
+# 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.
+
+coreWebXmlFile=core/src/main/webapp/WEB-INF/web.xml
+jBossDeploymentStructureXmlFile=core/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
+glassfishCoreWebXmlFile=core/src/main/webapp/WEB-INF/glassfish-web.xml
+tokenValueMapFile=oryx.debug.js-tokenValueMap.properties
+consoleResDirectory=console/src/main/resources
+pomFile=pom.xml
+persistenceContextEMFactoryFile=core/src/main/resources/persistenceContextEMFactory.xml
+coreMetaInfDirectory=core/src/main/resources/META-INF
+ormXmlFile=orm.xml
+ormXmlOracle=orm.xml.oracle
+ormXmlOracleSqlServer=orm.xml.sqlserver
+persistencePropertiesFile=core/src/main/resources/persistence.properties
+consolePropertiesFile=console.properties
+modelerPomFile=modelerPom.xml
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/resources/izpack/ProcessPanel.Spec.xml
----------------------------------------------------------------------
diff --git a/installer/src/main/resources/izpack/ProcessPanel.Spec.xml b/installer/src/main/resources/izpack/ProcessPanel.Spec.xml
index db1a64f..859ec18 100644
--- a/installer/src/main/resources/izpack/ProcessPanel.Spec.xml
+++ b/installer/src/main/resources/izpack/ProcessPanel.Spec.xml
@@ -64,23 +64,29 @@ under the License.
       <arg>$tomcat.container.port</arg><!-- 6 -->
       <arg>$tomcat.container.user</arg><!-- 7 -->
       <arg>$tomcat.container.pwd</arg><!-- 8 -->
-      <arg>$glassfish.container.dir</arg><!-- 9 -->
-      <arg>$mvn.conf.directory</arg><!-- 10 -->
-      <arg>$mvn.log.directory</arg><!-- 11 -->
-      <arg>$mvn.bundle.directory</arg><!-- 12 -->
-      <arg>$with.datasuorce</arg><!-- 13 -->
-      <arg>$jboss.container.ssl</arg><!-- 14 -->
-      <arg>$jboss.container.host</arg><!-- 15 -->
-      <arg>$jboss.container.port</arg><!-- 16 -->
-      <arg>$jboss.container.jdbc.module</arg><!-- 17 -->
-      <arg>$jboss.container.user</arg><!-- 18 -->
-      <arg>$jboss.container.pwd</arg><!-- 19 -->
-      <arg>$mvn.proxy</arg><!-- 20 -->
-      <arg>$mvn.proxy.host</arg><!-- 21 -->
-      <arg>$mvn.proxy.port</arg><!-- 22 -->
-      <arg>$mvn.proxy.user</arg><!-- 23 -->
-      <arg>$mvn.proxy.pwd</arg><!-- 24 -->
-      <arg>$mvn.proxy.autoconf</arg><!-- 25 -->
+      <arg>$glassfish.container.ssl</arg><!-- 9 -->
+      <arg>$glassfish.container.host</arg><!-- 10 -->
+      <arg>$glassfish.container.port</arg><!--11 -->
+      <arg>$glassfish.container.dir</arg><!-- 12 -->
+      <arg>$mvn.conf.directory</arg><!-- 13 -->
+      <arg>$mvn.log.directory</arg><!-- 14 -->
+      <arg>$mvn.bundle.directory</arg><!-- 15 -->
+      <arg>$with.datasuorce</arg><!-- 16 -->
+      <arg>$jboss.container.ssl</arg><!-- 17 -->
+      <arg>$jboss.container.host</arg><!-- 18 -->
+      <arg>$jboss.container.port</arg><!-- 19 -->
+      <arg>$jboss.container.jdbc.module</arg><!-- 20 -->
+      <arg>$jboss.container.user</arg><!-- 21 -->
+      <arg>$jboss.container.pwd</arg><!-- 22 -->
+      <arg>$jboss.container.management.port</arg><!-- 23 -->
+      <arg>$mvn.proxy</arg><!-- 24 -->
+      <arg>$mvn.proxy.host</arg><!-- 25 -->
+      <arg>$mvn.proxy.port</arg><!-- 26 -->
+      <arg>$mvn.proxy.user</arg><!-- 27 -->
+      <arg>$mvn.proxy.pwd</arg><!-- 28 -->
+      <arg>$mvn.proxy.autoconf</arg><!-- 29 -->
+      <arg>$mvn.proxy.autoconf</arg><!-- 30 -->
+      <arg>$mvn.proxy.autoconf</arg><!-- 31 -->
     </executeclass>
   </job>
   <onFail previous="true" next="false" />

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/resources/izpack/install.xml
----------------------------------------------------------------------
diff --git a/installer/src/main/resources/izpack/install.xml b/installer/src/main/resources/izpack/install.xml
index c7795f8..f2c35b8 100644
--- a/installer/src/main/resources/izpack/install.xml
+++ b/installer/src/main/resources/izpack/install.xml
@@ -33,7 +33,7 @@ under the License.
     <javaversion>${targetJdk}</javaversion>
   </info>
   
-  <guiprefs resizable="no" width="800" height="600">
+  <guiprefs resizable="no" width="800" height="600">    
     <modifier key="useButtonIcons" value="yes"/>
     <modifier key="useLabelIcons" value="no"/>
     <modifier key="labelGap" value="2"/>
@@ -55,7 +55,7 @@ under the License.
     <variable name="InstallerFrame.logfilePath" value="Default"/>
     <variable name="WELCOME_TEXT" value="Apache Syncope Installer"/>
     <variable name="WELCOME_VERSION" value="${appversion}"/>
-    <variable name="TargetPanel.dir.unix" value="/tmp/syncope"/>
+    <variable name="TargetPanel.dir.unix" value="/var/tmp/syncope"/>
     <variable name="TargetPanel.dir.windows" value="C:\Program Files"/>
   </variables>
   
@@ -170,6 +170,6 @@ under the License.
     <pack name="Apache Syncope" required="yes">
       <description>Apache Syncope Installer</description>
     </pack>
-  </packs>
+  </packs> 
   
 </izpack:installation>

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/resources/izpack/userInputLang.xml_eng
----------------------------------------------------------------------
diff --git a/installer/src/main/resources/izpack/userInputLang.xml_eng b/installer/src/main/resources/izpack/userInputLang.xml_eng
index 65ab5c9..00f183f 100644
--- a/installer/src/main/resources/izpack/userInputLang.xml_eng
+++ b/installer/src/main/resources/izpack/userInputLang.xml_eng
@@ -52,6 +52,9 @@ under the License.
   <str id="tomcat.container.pwd.id" txt="Tomcat password:"/>
   
   <str id="glassfish.container.dir.id" txt="Glassfish home directory:"/>
+  <str id="glassfish.container.ssl.id" txt="Https"/>
+  <str id="glassfish.container.host.id" txt="Glassfish host:"/>
+  <str id="glassfish.container.port.id" txt="Glassfish port:"/>
   
   <str id="jboss.container.ssl.id" txt="Https"/>
   <str id="jboss.container.host.id" txt="Jboss host:"/>
@@ -59,4 +62,5 @@ under the License.
   <str id="jboss.container.jdbc.module.id" txt="Jboss JDBC module name:"/>
   <str id="jboss.container.user.id" txt="Jboss admin username:"/>
   <str id="jboss.container.pwd.id" txt="Jboss admin password:"/>
+  <str id='jboss.container.management.port.id' txt="Jboss management port"/>
 </langpack>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/resources/izpack/userInputLang.xml_ita
----------------------------------------------------------------------
diff --git a/installer/src/main/resources/izpack/userInputLang.xml_ita b/installer/src/main/resources/izpack/userInputLang.xml_ita
index d60fc56..65dc51f 100644
--- a/installer/src/main/resources/izpack/userInputLang.xml_ita
+++ b/installer/src/main/resources/izpack/userInputLang.xml_ita
@@ -52,6 +52,9 @@ under the License.
   <str id="tomcat.container.pwd.id" txt="Tomcat password:"/>
   
   <str id="glassfish.container.dir.id" txt="Glassfish home directory:"/>
+  <str id="glassfish.container.ssl.id" txt="Https"/>
+  <str id="glassfish.container.host.id" txt="Glassfish host:"/>
+  <str id="glassfish.container.port.id" txt="Glassfish port:"/>
   
   <str id="jboss.container.ssl.id" txt="Https"/>
   <str id="jboss.container.host.id" txt="Jboss host:"/>
@@ -59,4 +62,5 @@ under the License.
   <str id="jboss.container.jdbc.module.id" txt="Jboss JDBC module name:"/>
   <str id="jboss.container.user.id" txt="Jboss admin username:"/>
   <str id="jboss.container.pwd.id" txt="Jboss admin password:"/>
+  <str id='jboss.container.management.port.id' txt="Jbos management port"/>
 </langpack>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/resources/izpack/userInputSpec.xml
----------------------------------------------------------------------
diff --git a/installer/src/main/resources/izpack/userInputSpec.xml b/installer/src/main/resources/izpack/userInputSpec.xml
index bf1ce27..0253a33 100644
--- a/installer/src/main/resources/izpack/userInputSpec.xml
+++ b/installer/src/main/resources/izpack/userInputSpec.xml
@@ -131,7 +131,7 @@ under the License.
       <spec id="persistence.jdbc.url" size="20" set="jdbc:oracle:thin:@localhost:1521:orcl"/>
     </field>
     <field type="text" variable="persistence.url" conditionid="sqlserver.choice">
-      <spec id="persistence.jdbc.url" size="20" set="jdbc:sqlserver://localhost:1344;database=syncope;selectMethod=cursor;sendStringParametersAsUnicode=false"/>
+      <spec id="persistence.jdbc.url" size="20" set="jdbc:sqlserver://localhost:1433;database=syncope;selectMethod=cursor;sendStringParametersAsUnicode=false"/>
     </field>
     <field type="space"/>
     <field type="text" variable="persistence.dbuser">
@@ -200,6 +200,18 @@ under the License.
       <spec id="tomcat.container.pwd.id" size="20" set="s3cret"/>
     </field>
     
+    <field type="check" variable="glassfish.container.ssl" conditionid="glassfish.choice">
+      <spec id="glassfish.container.ssl.id" true="true" false="false" set="false"/>
+    </field>
+    <field type="space"/>
+    <field type="text" variable="glassfish.container.host" conditionid="glassfish.choice">
+      <spec id="glassfish.container.host.id" size="20" set="localhost"/>
+    </field>
+    <field type="space"/>
+    <field type="text" variable="glassfish.container.port" conditionid="glassfish.choice">
+      <spec id="glassfish.container.port.id" size="20" set="8080"/>
+    </field>
+    <field type="space"/>
     <field type="text" variable="glassfish.container.dir" conditionid="glassfish.choice">
       <spec id="glassfish.container.dir.id" size="20" set="/opt/glassfish4/"/>
     </field>
@@ -213,7 +225,7 @@ under the License.
     </field>
     <field type="space"/>
     <field type="text" variable="jboss.container.port" conditionid="jboss.choice">
-      <spec id="jboss.container.port.id" size="20" set="9990"/>
+      <spec id="jboss.container.port.id" size="20" set="8080"/>
     </field>
     <field type="space"/>
     <field type="text" variable="jboss.container.jdbc.module" conditionid="jboss.choice">
@@ -227,5 +239,9 @@ under the License.
     <field type="text" variable="jboss.container.pwd" conditionid="jboss.choice">
       <spec id="jboss.container.pwd.id" size="20" set="password"/>
     </field>
+    <field type="space"/>
+    <field type="text" variable="jboss.container.management.port" conditionid="jboss.choice">
+      <spec id="jboss.container.management.port.id" size="20" set="9990"/>
+    </field> 
   </panel>
 </userInput>

http://git-wip-us.apache.org/repos/asf/syncope/blob/5e013aa4/installer/src/main/resources/modelerPom.xml
----------------------------------------------------------------------
diff --git a/installer/src/main/resources/modelerPom.xml b/installer/src/main/resources/modelerPom.xml
new file mode 100644
index 0000000..8b65ba6
--- /dev/null
+++ b/installer/src/main/resources/modelerPom.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+   
+  <groupId>org.apache.syncope</groupId>
+  <artifactId>activitiModelerSetup</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <packaging>jar</packaging>
+   
+  <properties>
+    <activiti.version>5.16.2</activiti.version>
+    <activiti-modeler.directory>${modeler.directory}</activiti-modeler.directory>
+    <tokenValueMap>${modeler.directory}/oryx.debug.js-tokenValueMap.properties</tokenValueMap>
+     
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+   
+  <dependencies>
+    <dependency>
+      <groupId>org.activiti</groupId>
+      <artifactId>activiti-webapp-explorer2</artifactId>           
+      <version>${activiti.version}</version>
+      <type>war</type>
+      <scope>test</scope>
+    </dependency>   
+  </dependencies>
+   
+  <build>   
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <version>1.7</version>
+        <executions>
+          <execution>
+            <id>setupActivitiModeler</id>
+            <phase>process-resources</phase>
+            <configuration>
+              <target>
+                <unzip src="${settings.localRepository}/org/activiti/activiti-webapp-explorer2/${activiti.version}/activiti-webapp-explorer2-${activiti.version}.war"
+                       dest="${project.build.directory}/activiti-webapp-explorer2" />
+                 
+                <mkdir dir="${activiti-modeler.directory}" />
+                 
+                <mkdir dir="${activiti-modeler.directory}/editor" />
+                <copy todir="${activiti-modeler.directory}/editor">
+                  <fileset dir="${project.build.directory}/activiti-webapp-explorer2/editor">
+                    <exclude name="oryx.js" />
+                  </fileset>
+                </copy>
+                <copy file="${project.build.directory}/activiti-webapp-explorer2/WEB-INF/classes/plugins.xml"
+                      todir="${activiti-modeler.directory}/editor" />
+                <copy file="${project.build.directory}/activiti-webapp-explorer2/WEB-INF/classes/stencilset.json"
+                      todir="${activiti-modeler.directory}/editor" />
+                 
+                <mkdir dir="${activiti-modeler.directory}/explorer" />
+                <copy todir="${activiti-modeler.directory}/explorer">
+                  <fileset dir="${project.build.directory}/activiti-webapp-explorer2/explorer" />
+                </copy>
+                 
+                <mkdir dir="${activiti-modeler.directory}/libs" />
+                <copy todir="${activiti-modeler.directory}/libs">
+                  <fileset dir="${project.build.directory}/activiti-webapp-explorer2/libs" />
+                </copy>
+              </target>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>com.google.code.maven-replacer-plugin</groupId>
+        <artifactId>replacer</artifactId>
+        <version>1.5.3</version>
+        <executions>
+          <execution>
+            <phase>process-resources</phase>
+            <goals>
+              <goal>replace</goal>
+            </goals>                  
+          </execution>
+        </executions>
+        <configuration>
+          <file>${activiti-modeler.directory}/editor/oryx.debug.js</file>
+          <tokenValueMap>${tokenValueMap}</tokenValueMap>
+          <unescape>true</unescape>
+          <regex>false</regex>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>


[20/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/resources/content.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/content.xml b/syncope620/server/persistence-jpa/src/main/resources/content.xml
new file mode 100644
index 0000000..827e6c9
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/resources/content.xml
@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<dataset>
+  <SyncopeConf id="1" 
+               creator="admin" lastModifier="admin"
+               creationDate="2014-06-20 11:00:00" lastChangeDate="2014-06-20 11:00:00"/>
+
+  <CSchema name="password.cipher.algorithm" type="String"
+           mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CAttr id="1" owner_id="1" schema_name="password.cipher.algorithm"/>
+  <CAttrValue id="1" attribute_id="1" stringValue="SHA1"/>
+
+  <!-- notificationjob.cronExpression:
+  + not existing: NotificationJob runs according to Notification.DEFAULT_CRON_EXP
+  + provided as empty string: NotificationJob disabled
+  + provided as non-empty string: NotificationJob runs according to the given value -->
+  <CSchema name="notificationjob.cronExpression" type="String"
+           mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CAttr id="2" owner_id="1" schema_name="notificationjob.cronExpression"/>
+  <CAttrValue id="2" attribute_id="2" stringValue=""/>
+
+  <CSchema name="notification.maxRetries" type="Long"
+           mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CAttr id="3" owner_id="1" schema_name="notification.maxRetries"/>
+  <CAttrValue id="3" attribute_id="3" longValue="0"/>
+
+  <CSchema name="token.length" type="Long"
+           mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CAttr id="4" owner_id="1" schema_name="token.length"/>
+  <CAttrValue id="4" attribute_id="4" longValue="256"/>
+
+  <CSchema name="token.expireTime" type="Long"
+           mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CAttr id="5" owner_id="1" schema_name="token.expireTime"/>
+  <CAttrValue id="5" attribute_id="5" longValue="60"/>
+
+  <CSchema name="selfRegistration.allowed" type="Boolean"
+           mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CAttr id="6" owner_id="1" schema_name="selfRegistration.allowed"/>
+  <CAttrValue id="6" attribute_id="6" booleanValue="1"/>
+
+  <CSchema name="passwordReset.allowed" type="Boolean"
+           mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CAttr id="7" owner_id="1" schema_name="passwordReset.allowed"/>
+  <CAttrValue id="7" attribute_id="7" booleanValue="1"/>
+
+  <CSchema name="passwordReset.securityQuestion" type="Boolean"
+           mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CAttr id="8" owner_id="1" schema_name="passwordReset.securityQuestion"/>
+  <CAttrValue id="8" attribute_id="8" booleanValue="1"/>
+
+  <CSchema name="authentication.statuses" type="String"
+           mandatoryCondition="true" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CAttr id="9" owner_id="1" schema_name="authentication.statuses"/>
+  <CAttrValue id="9" attribute_id="9" stringValue="created"/>
+  <CAttrValue id="10" attribute_id="9" stringValue="active"/>
+
+  <!-- Save user login date upon successful authentication -->
+  <CSchema name="log.lastlogindate" type="Boolean"
+           mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CAttr id="11" owner_id="1" schema_name="log.lastlogindate"/>
+  <CAttrValue id="11" attribute_id="11" booleanValue="1"/>
+
+  <!-- For usage with admin console -->
+  <CSchema name="admin.user.layout" type="String"
+           mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CSchema name="self.user.layout" type="String"
+           mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CSchema name="admin.role.layout" type="String"
+           mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CSchema name="self.role.layout" type="String"
+           mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CSchema name="admin.membership.layout" type="String"
+           mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CSchema name="self.membership.layout" type="String"
+           mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+        
+  <!-- User pre-defined schemas -->
+  <USchema name="email" type="String"
+           mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
+           validatorClass="org.apache.syncope.core.persistence.validation.attrvalue.EmailAddressValidator"/>  
+  
+  <!-- Password reset notifications -->
+  <Notification id="1" active="1" recipientAttrName="email" recipientAttrType="UserSchema" selfAsRecipient="1" 
+                sender="admin@syncope.apache.org" subject="Password Reset request" template="requestPasswordReset" 
+                traceLevel="FAILURES" userAbout="token!=$null"/> 
+  <Notification_events Notification_id="1" events="[CUSTOM]:[]:[]:[requestPasswordReset]:[SUCCESS]"/>
+  
+  <Notification id="2" active="1" recipientAttrName="email" recipientAttrType="UserSchema" selfAsRecipient="1" 
+                sender="admin@syncope.apache.org" subject="Password Reset successful" template="confirmPasswordReset" 
+                traceLevel="FAILURES" userAbout="token!=$null"/> 
+  <Notification_events Notification_id="2" events="[CUSTOM]:[]:[]:[confirmPasswordReset]:[SUCCESS]"/>  
+  
+  <!-- Authentication and authorization -->
+  <Entitlement name="SCHEMA_LIST"/>
+  <Entitlement name="SCHEMA_CREATE"/>
+  <Entitlement name="SCHEMA_READ"/>
+  <Entitlement name="SCHEMA_UPDATE"/>
+  <Entitlement name="SCHEMA_DELETE"/>
+  <Entitlement name="USER_LIST"/>
+  <Entitlement name="USER_CREATE"/>
+  <Entitlement name="USER_READ"/>
+  <Entitlement name="USER_UPDATE"/>
+  <Entitlement name="USER_DELETE"/>
+  <Entitlement name="USER_VIEW"/>
+  <Entitlement name="ROLE_LIST"/>
+  <Entitlement name="ROLE_CREATE"/>
+  <Entitlement name="ROLE_READ"/>
+  <Entitlement name="ROLE_UPDATE"/>
+  <Entitlement name="ROLE_DELETE"/>
+  <Entitlement name="RESOURCE_LIST"/>
+  <Entitlement name="RESOURCE_CREATE"/>
+  <Entitlement name="RESOURCE_READ"/>
+  <Entitlement name="RESOURCE_UPDATE"/>
+  <Entitlement name="RESOURCE_DELETE"/>
+  <Entitlement name="RESOURCE_GETCONNECTOROBJECT"/>
+  <Entitlement name="CONNECTOR_LIST"/>
+  <Entitlement name="CONNECTOR_CREATE"/>
+  <Entitlement name="CONNECTOR_READ"/>
+  <Entitlement name="CONNECTOR_UPDATE"/>
+  <Entitlement name="CONNECTOR_DELETE"/>
+  <Entitlement name="CONNECTOR_RELOAD"/>
+  <Entitlement name="CONFIGURATION_EXPORT"/>
+  <Entitlement name="CONFIGURATION_LIST"/>
+  <Entitlement name="CONFIGURATION_SET"/>
+  <Entitlement name="CONFIGURATION_DELETE"/>
+  <Entitlement name="TASK_LIST"/>
+  <Entitlement name="TASK_CREATE"/>
+  <Entitlement name="TASK_READ"/>
+  <Entitlement name="TASK_UPDATE"/>
+  <Entitlement name="TASK_DELETE"/>
+  <Entitlement name="TASK_EXECUTE"/>
+  <Entitlement name="POLICY_LIST"/>
+  <Entitlement name="POLICY_CREATE"/>
+  <Entitlement name="POLICY_READ"/>
+  <Entitlement name="POLICY_UPDATE"/>
+  <Entitlement name="POLICY_DELETE"/>
+  <Entitlement name="WORKFLOW_DEF_READ"/>
+  <Entitlement name="WORKFLOW_DEF_UPDATE"/>
+  <Entitlement name="WORKFLOW_TASK_LIST"/> 
+  <Entitlement name="WORKFLOW_FORM_LIST"/>
+  <Entitlement name="WORKFLOW_FORM_READ"/>
+  <Entitlement name="WORKFLOW_FORM_CLAIM"/>
+  <Entitlement name="WORKFLOW_FORM_SUBMIT"/>
+  <Entitlement name="NOTIFICATION_LIST"/>
+  <Entitlement name="NOTIFICATION_CREATE"/>
+  <Entitlement name="NOTIFICATION_READ"/>
+  <Entitlement name="NOTIFICATION_UPDATE"/>
+  <Entitlement name="NOTIFICATION_DELETE"/>
+  <Entitlement name="REPORT_LIST"/>
+  <Entitlement name="REPORT_READ"/>
+  <Entitlement name="REPORT_CREATE"/>
+  <Entitlement name="REPORT_UPDATE"/>
+  <Entitlement name="REPORT_DELETE"/>
+  <Entitlement name="REPORT_EXECUTE"/>
+  <Entitlement name="LOG_LIST"/>
+  <Entitlement name="LOG_SET_LEVEL"/>
+  <Entitlement name="LOG_DELETE"/>
+  <Entitlement name="AUDIT_LIST"/>
+  <Entitlement name="AUDIT_ENABLE"/>
+  <Entitlement name="AUDIT_DISABLE"/>
+  <Entitlement name="SECURITY_QUESTION_CREATE"/>
+  <Entitlement name="SECURITY_QUESTION_UPDATE"/>
+  <Entitlement name="SECURITY_QUESTION_DELETE"/>
+
+</dataset>

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/resources/indexes.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/indexes.xml b/syncope620/server/persistence-jpa/src/main/resources/indexes.xml
new file mode 100644
index 0000000..effcb7b
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/resources/indexes.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+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.
+-->
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+  <comment>Additional indexes (in respect to JPA's)</comment>
+
+  <entry key="UPlainAttrValue_stringvalueIndex">CREATE INDEX UAttrValue_stringvalueIndex ON UPlainAttrValue(stringvalue)</entry>
+  <entry key="UPlainAttrValue_datevalueIndex">CREATE INDEX UAttrValue_datevalueIndex ON UPlainAttrValue(datevalue)</entry>
+  <entry key="UPlainAttrValue_longvalueIndex">CREATE INDEX UAttrValue_longvalueIndex ON UPlainAttrValue(longvalue)</entry>
+  <entry key="UPlainAttrValue_doublevalueIndex">CREATE INDEX UAttrValue_doublevalueIndex ON UPlainAttrValue(doublevalue)</entry>
+  <entry key="UPlainAttrValue_booleanvalueIndex">CREATE INDEX UAttrValue_booleanvalueIndex ON UPlainAttrValue(booleanvalue)</entry>
+  <entry key="MPlainAttrValue_stringvalueIndex">CREATE INDEX MAttrValue_stringvalueIndex ON MPlainAttrValue(stringvalue)</entry>
+  <entry key="MPlainAttrValue_datevalueIndex">CREATE INDEX MAttrValue_datevalueIndex ON MPlainAttrValue(datevalue)</entry>
+  <entry key="MPlainAttrValue_longvalueIndex">CREATE INDEX MAttrValue_longvalueIndex ON MPlainAttrValue(longvalue)</entry>
+  <entry key="MPlainAttrValue_doublevalueIndex">CREATE INDEX MAttrValue_doublevalueIndex ON MPlainAttrValue(doublevalue)</entry>
+  <entry key="MPlainAttrValue_booleanvalueIndex">CREATE INDEX MAttrValue_booleanvalueIndex ON MPlainAttrValue(booleanvalue)</entry>
+  <entry key="RPlainAttrValue_stringvalueIndex">CREATE INDEX RAttrValue_stringvalueIndex ON RPlainAttrValue(stringvalue)</entry>
+  <entry key="RPlainAttrValue_datevalueIndex">CREATE INDEX RAttrValue_datevalueIndex ON RPlainAttrValue(datevalue)</entry>
+  <entry key="RPlainAttrValue_longvalueIndex">CREATE INDEX RAttrValue_longvalueIndex ON RPlainAttrValue(longvalue)</entry>
+  <entry key="RPlainAttrValue_doublevalueIndex">CREATE INDEX RAttrValue_doublevalueIndex ON RPlainAttrValue(doublevalue)</entry>
+  <entry key="RPlainAttrValue_booleanvalueIndex">CREATE INDEX RAttrValue_booleanvalueIndex ON RPlainAttrValue(booleanvalue)</entry>
+  <entry key="Task_executedIndex">CREATE INDEX Task_executedIndex ON Task(executed)</entry>
+</properties>

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/resources/persistence.properties
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/persistence.properties b/syncope620/server/persistence-jpa/src/main/resources/persistence.properties
new file mode 100644
index 0000000..a737b93
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/resources/persistence.properties
@@ -0,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.
+jpa.driverClassName=org.postgresql.Driver
+jpa.url=jdbc:postgresql://localhost:5432/syncope
+jpa.username=syncope
+jpa.password=syncope
+jpa.dialect=org.apache.openjpa.jdbc.sql.PostgresDictionary
+jpa.pool.validationQuery=SELECT 1
+#note: other connection pool settings can also be configured here, see persistenceContext.xml
+quartz.jobstore=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
+quartz.sql=tables_postgres.sql
+audit.sql=audit.sql
+database.schema=
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/resources/persistenceContext.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/persistenceContext.xml b/syncope620/server/persistence-jpa/src/main/resources/persistenceContext.xml
new file mode 100644
index 0000000..df0b795
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/resources/persistenceContext.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xmlns:tx="http://www.springframework.org/schema/tx"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+                           http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/context
+                           http://www.springframework.org/schema/context/spring-context.xsd
+                           http://www.springframework.org/schema/tx
+                           http://www.springframework.org/schema/tx/spring-tx.xsd
+                           http://www.springframework.org/schema/util
+                           http://www.springframework.org/schema/util/spring-util.xsd">
+
+  
+  <import resource="persistenceContextEMFactory.xml"/>
+
+  <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+    <property name="locations">
+      <list>
+        <value>classpath:persistence.properties</value>
+      </list>
+    </property>
+    <property name="ignoreResourceNotFound" value="true"/>
+    <property name="ignoreUnresolvablePlaceholders" value="true"/>
+  </bean>
+
+  <bean id="nonJPAdbInitializer" class="org.springframework.jdbc.datasource.init.DataSourceInitializer">
+    <property name="dataSource" ref="dataSource"/>
+    <property name="enabled" value="true"/>
+    <property name="databasePopulator">
+      <bean class="org.springframework.jdbc.datasource.init.ResourceDatabasePopulator">
+        <property name="continueOnError" value="true"/>
+        <property name="ignoreFailedDrops" value="true"/>
+        <property name="sqlScriptEncoding" value="UTF-8"/>
+        <property name="scripts">
+          <array>
+            <value type="org.springframework.core.io.Resource">
+              classpath:/quartz/${quartz.sql}
+            </value>
+          </array>
+        </property>
+      </bean>
+    </property>
+  </bean>
+  
+  <context:annotation-config/>
+  <context:component-scan base-package="org.apache.syncope.persistence.jpa"/>
+
+  <bean id="database.schema" class="java.lang.String">
+    <constructor-arg value="${database.schema}"/>
+  </bean>
+  <bean id="persistenceProperties" class="org.apache.syncope.server.spring.ResourceWithFallbackLoader">
+    <property name="primary" value="file:${conf.directory}/persistence.properties"/>
+    <property name="fallback" value="classpath:persistence.properties"/>
+  </bean>
+  <bean id="contentXML" class="org.apache.syncope.server.spring.ResourceWithFallbackLoader">
+    <property name="primary" value="file:${conf.directory}/content.xml"/>
+    <property name="fallback" value="classpath:content.xml"/>
+  </bean>
+  <bean id="viewsXML" class="org.apache.syncope.server.spring.ResourceWithFallbackLoader">
+    <property name="primary" value="file:${conf.directory}/views.xml"/>
+    <property name="fallback" value="classpath:views.xml"/>
+  </bean>
+  <bean id="indexesXML" class="org.apache.syncope.server.spring.ResourceWithFallbackLoader">
+    <property name="primary" value="file:${conf.directory}/indexes.xml"/>
+    <property name="fallback" value="classpath:indexes.xml"/>
+  </bean>
+
+  <!-- Use JNDI datasource as default but, when not available, revert to
+  local datasource, with different properties for execution and testing. 
+  In any case, get all JDBC connections with a determined isolation level. -->
+  <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
+    <property name="jndiName" value="java:comp/env/jdbc/syncopeDataSource"/>
+    <property name="defaultObject" ref="localDataSource"/>
+  </bean>
+
+  <bean id="localDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
+    <property name="driverClassName" value="${jpa.driverClassName}"/>
+    <property name="url" value="${jpa.url}"/>
+    <property name="username" value="${jpa.username}"/>
+    <property name="password" value="${jpa.password}"/>
+    <!-- connection pool configuration - transaction isolation, default READ_COMMITTED (see SYNCOPE-202) -->
+    <property name="defaultTransactionIsolation">
+      <util:constant static-field="${jpa.pool.defaultTransactionIsolation:java.sql.Connection.TRANSACTION_READ_COMMITTED}"/>
+    </property>
+    <!-- connection pool configuration - default values taken from BasicDataSource default values -->
+    <property name="initialSize" value="${jpa.pool.initialSize:0}"/>
+    <property name="maxTotal" value="${jpa.pool.maxActive:8}"/>
+    <property name="maxIdle" value="${jpa.pool.maxIdle:8}"/>
+    <property name="minIdle" value="${jpa.pool.minIdle:0}"/>
+    <property name="maxWaitMillis" value="${jpa.pool.maxWait:-1}"/>
+    <property name="validationQuery" value="${jpa.pool.validationQuery}"/>
+    <property name="validationQueryTimeout" value="${jpa.pool.validationQueryTimeout:-1}"/>
+    <property name="testOnBorrow" value="${jpa.pool.testOnBorrow:true}"/>
+    <property name="testOnReturn" value="${jpa.pool.testOnReturn:false}"/>
+    <property name="testWhileIdle" value="${jpa.pool.testWhileIdle:false}"/>
+    <property name="timeBetweenEvictionRunsMillis" value="${jpa.pool.timeBetweenEvictionRunsMillis:-1}"/>
+    <property name="numTestsPerEvictionRun" value="${jpa.pool.numTestsPerEvictionRun:3}"/>
+    <property name="minEvictableIdleTimeMillis" value="${jpa.pool.minEvictableIdleTimeMillis:1800000}"/>
+    <property name="removeAbandonedOnBorrow" value="${jpa.pool.removeAbandoned:false}"/>
+    <property name="removeAbandonedOnMaintenance" value="${jpa.pool.removeAbandoned:false}"/>
+    <property name="removeAbandonedTimeout" value="${jpa.pool.removeAbandonedTimeout:300}"/>
+    <property name="logAbandoned" value="${jpa.pool.logAbandoned:false}"/>
+  </bean>
+
+  <bean id="entityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
+    <property name="entityManagerFactory" ref="entityManagerFactory"/>
+  </bean>
+
+  <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
+    <property name="entityManagerFactory" ref="entityManagerFactory"/>
+  </bean>
+  <tx:annotation-driven/>
+
+  <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
+</beans>

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/resources/persistenceContextEMFactory.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/persistenceContextEMFactory.xml b/syncope620/server/persistence-jpa/src/main/resources/persistenceContextEMFactory.xml
new file mode 100644
index 0000000..3337dd3
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/resources/persistenceContextEMFactory.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+                           http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+  <bean id="entityManagerFactory"
+        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
+    <property name="persistenceXmlLocation" value="classpath*:META-INF/spring-persistence.xml"/>
+    <property name="persistenceUnitName" value="syncopePersistenceUnit"/>
+    <property name="dataSource" ref="dataSource"/>
+    <property name="jpaVendorAdapter">
+      <bean class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter">
+        <property name="showSql" value="false"/>
+        <property name="generateDdl" value="true"/>
+        <property name="databasePlatform" value="${jpa.dialect}"/>
+      </bean>
+    </property>
+    <property name="jpaPropertyMap">
+      <map>
+        <!--<entry key="openjpa.Log" value="SQL=TRACE"/>
+        <entry key="openjpa.ConnectionFactoryProperties" 
+               value="PrintParameters=true, PrettyPrint=true, PrettyPrintLineLength=80"/>-->
+                
+        <entry key="openjpa.NontransactionalWrite" value="false"/>
+        <entry key="openjpa.AutoDetach" value="close, commit, nontx-read, rollback"/>
+
+        <entry key="openjpa.jdbc.SchemaFactory" value="native(ForeignKeys=true)"/>
+        <entry key="openjpa.jdbc.MappingDefaults" value="ForeignKeyDeleteAction=restrict, JoinForeignKeyDeleteAction=restrict"/>
+                
+        <entry key="openjpa.DataCache" value="true"/>
+        <entry key="openjpa.QueryCache" value="true"/>
+        <entry key="openjpa.RemoteCommitProvider" value="sjvm"/>
+      </map>
+    </property>
+  </bean>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_h2.sql
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_h2.sql b/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_h2.sql
new file mode 100644
index 0000000..e798223
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_h2.sql
@@ -0,0 +1,266 @@
+-- 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.
+
+-- Thanks to Amir Kibbar and Peter Rietzler for contributing the schema for H2 database, 
+-- and verifying that it works with Quartz's StdJDBCDelegate
+--
+-- Note, Quartz depends on row-level locking which means you must use the MVCC=TRUE 
+-- setting on your H2 database, or you will experience dead-locks
+--
+--
+-- In your Quartz properties file, you'll need to set 
+-- org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
+
+CREATE TABLE QRTZ_CALENDARS (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  CALENDAR_NAME VARCHAR (200)  NOT NULL ,
+  CALENDAR IMAGE NOT NULL
+);
+
+CREATE TABLE QRTZ_CRON_TRIGGERS (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  TRIGGER_NAME VARCHAR (200)  NOT NULL ,
+  TRIGGER_GROUP VARCHAR (200)  NOT NULL ,
+  CRON_EXPRESSION VARCHAR (120)  NOT NULL ,
+  TIME_ZONE_ID VARCHAR (80) 
+);
+
+CREATE TABLE QRTZ_FIRED_TRIGGERS (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  ENTRY_ID VARCHAR (95)  NOT NULL ,
+  TRIGGER_NAME VARCHAR (200)  NOT NULL ,
+  TRIGGER_GROUP VARCHAR (200)  NOT NULL ,
+  INSTANCE_NAME VARCHAR (200)  NOT NULL ,
+  FIRED_TIME BIGINT NOT NULL ,
+  SCHED_TIME BIGINT NOT NULL ,
+  PRIORITY INTEGER NOT NULL ,
+  STATE VARCHAR (16)  NOT NULL,
+  JOB_NAME VARCHAR (200)  NULL ,
+  JOB_GROUP VARCHAR (200)  NULL ,
+  IS_NONCONCURRENT BOOLEAN  NULL ,
+  REQUESTS_RECOVERY BOOLEAN  NULL 
+);
+
+CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  TRIGGER_GROUP VARCHAR (200)  NOT NULL 
+);
+
+CREATE TABLE QRTZ_SCHEDULER_STATE (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  INSTANCE_NAME VARCHAR (200)  NOT NULL ,
+  LAST_CHECKIN_TIME BIGINT NOT NULL ,
+  CHECKIN_INTERVAL BIGINT NOT NULL
+);
+
+CREATE TABLE QRTZ_LOCKS (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  LOCK_NAME VARCHAR (40)  NOT NULL 
+);
+
+CREATE TABLE QRTZ_JOB_DETAILS (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  JOB_NAME VARCHAR (200)  NOT NULL ,
+  JOB_GROUP VARCHAR (200)  NOT NULL ,
+  DESCRIPTION VARCHAR (250) NULL ,
+  JOB_CLASS_NAME VARCHAR (250)  NOT NULL ,
+  IS_DURABLE BOOLEAN  NOT NULL ,
+  IS_NONCONCURRENT BOOLEAN  NOT NULL ,
+  IS_UPDATE_DATA BOOLEAN  NOT NULL ,
+  REQUESTS_RECOVERY BOOLEAN  NOT NULL ,
+  JOB_DATA IMAGE NULL
+);
+
+CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  TRIGGER_NAME VARCHAR (200)  NOT NULL ,
+  TRIGGER_GROUP VARCHAR (200)  NOT NULL ,
+  REPEAT_COUNT BIGINT NOT NULL ,
+  REPEAT_INTERVAL BIGINT NOT NULL ,
+  TIMES_TRIGGERED BIGINT NOT NULL
+);
+
+CREATE TABLE qrtz_simprop_triggers
+  (          
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    STR_PROP_1 VARCHAR(512) NULL,
+    STR_PROP_2 VARCHAR(512) NULL,
+    STR_PROP_3 VARCHAR(512) NULL,
+    INT_PROP_1 INTEGER NULL,
+    INT_PROP_2 INTEGER NULL,
+    LONG_PROP_1 BIGINT NULL,
+    LONG_PROP_2 BIGINT NULL,
+    DEC_PROP_1 NUMERIC(13,4) NULL,
+    DEC_PROP_2 NUMERIC(13,4) NULL,
+    BOOL_PROP_1 BOOLEAN NULL,
+    BOOL_PROP_2 BOOLEAN NULL,
+);
+
+CREATE TABLE QRTZ_BLOB_TRIGGERS (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  TRIGGER_NAME VARCHAR (200)  NOT NULL ,
+  TRIGGER_GROUP VARCHAR (200)  NOT NULL ,
+  BLOB_DATA IMAGE NULL
+);
+
+CREATE TABLE QRTZ_TRIGGERS (
+  SCHED_NAME VARCHAR(120) NOT NULL,
+  TRIGGER_NAME VARCHAR (200)  NOT NULL ,
+  TRIGGER_GROUP VARCHAR (200)  NOT NULL ,
+  JOB_NAME VARCHAR (200)  NOT NULL ,
+  JOB_GROUP VARCHAR (200)  NOT NULL ,
+  DESCRIPTION VARCHAR (250) NULL ,
+  NEXT_FIRE_TIME BIGINT NULL ,
+  PREV_FIRE_TIME BIGINT NULL ,
+  PRIORITY INTEGER NULL ,
+  TRIGGER_STATE VARCHAR (16)  NOT NULL ,
+  TRIGGER_TYPE VARCHAR (8)  NOT NULL ,
+  START_TIME BIGINT NOT NULL ,
+  END_TIME BIGINT NULL ,
+  CALENDAR_NAME VARCHAR (200)  NULL ,
+  MISFIRE_INSTR SMALLINT NULL ,
+  JOB_DATA IMAGE NULL
+);
+
+ALTER TABLE QRTZ_CALENDARS  ADD
+  CONSTRAINT PK_QRTZ_CALENDARS PRIMARY KEY  
+  (
+    SCHED_NAME,
+    CALENDAR_NAME
+  );
+
+ALTER TABLE QRTZ_CRON_TRIGGERS  ADD
+  CONSTRAINT PK_QRTZ_CRON_TRIGGERS PRIMARY KEY  
+  (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  );
+
+ALTER TABLE QRTZ_FIRED_TRIGGERS  ADD
+  CONSTRAINT PK_QRTZ_FIRED_TRIGGERS PRIMARY KEY  
+  (
+    SCHED_NAME,
+    ENTRY_ID
+  );
+
+ALTER TABLE QRTZ_PAUSED_TRIGGER_GRPS  ADD
+  CONSTRAINT PK_QRTZ_PAUSED_TRIGGER_GRPS PRIMARY KEY  
+  (
+    SCHED_NAME,
+    TRIGGER_GROUP
+  );
+
+ALTER TABLE QRTZ_SCHEDULER_STATE  ADD
+  CONSTRAINT PK_QRTZ_SCHEDULER_STATE PRIMARY KEY  
+  (
+    SCHED_NAME,
+    INSTANCE_NAME
+  );
+
+ALTER TABLE QRTZ_LOCKS  ADD
+  CONSTRAINT PK_QRTZ_LOCKS PRIMARY KEY  
+  (
+    SCHED_NAME,
+    LOCK_NAME
+  );
+
+ALTER TABLE QRTZ_JOB_DETAILS  ADD
+  CONSTRAINT PK_QRTZ_JOB_DETAILS PRIMARY KEY  
+  (
+    SCHED_NAME,
+    JOB_NAME,
+    JOB_GROUP
+  );
+
+ALTER TABLE QRTZ_SIMPLE_TRIGGERS  ADD
+  CONSTRAINT PK_QRTZ_SIMPLE_TRIGGERS PRIMARY KEY  
+  (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  );
+
+ALTER TABLE QRTZ_SIMPROP_TRIGGERS  ADD
+  CONSTRAINT PK_QRTZ_SIMPROP_TRIGGERS PRIMARY KEY  
+  (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  );
+
+ALTER TABLE QRTZ_TRIGGERS  ADD
+  CONSTRAINT PK_QRTZ_TRIGGERS PRIMARY KEY  
+  (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  );
+
+ALTER TABLE QRTZ_CRON_TRIGGERS ADD
+  CONSTRAINT FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS FOREIGN KEY
+  (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  ) REFERENCES QRTZ_TRIGGERS (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  ) ON DELETE CASCADE;
+
+
+ALTER TABLE QRTZ_SIMPLE_TRIGGERS ADD
+  CONSTRAINT FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS FOREIGN KEY
+  (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  ) REFERENCES QRTZ_TRIGGERS (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  ) ON DELETE CASCADE;
+
+ALTER TABLE QRTZ_SIMPROP_TRIGGERS ADD
+  CONSTRAINT FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS FOREIGN KEY
+  (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  ) REFERENCES QRTZ_TRIGGERS (
+    SCHED_NAME,
+    TRIGGER_NAME,
+    TRIGGER_GROUP
+  ) ON DELETE CASCADE;
+
+
+ALTER TABLE QRTZ_TRIGGERS ADD
+  CONSTRAINT FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS FOREIGN KEY
+  (
+    SCHED_NAME,
+    JOB_NAME,
+    JOB_GROUP
+  ) REFERENCES QRTZ_JOB_DETAILS (
+    SCHED_NAME,
+    JOB_NAME,
+    JOB_GROUP
+  );
+  
+COMMIT;

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_mysql.sql
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_mysql.sql b/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_mysql.sql
new file mode 100644
index 0000000..ebb8e59
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_mysql.sql
@@ -0,0 +1,206 @@
+-- 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.
+
+--
+-- Quartz seems to work best with the driver mm.mysql-2.0.7-bin.jar
+--
+-- PLEASE consider using mysql with innodb tables to avoid locking issues
+--
+-- In your Quartz properties file, you'll need to set 
+-- org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
+--
+
+BEGIN;
+DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
+DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
+DROP TABLE IF EXISTS QRTZ_LOCKS;
+DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
+DROP TABLE IF EXISTS QRTZ_CALENDARS;
+COMMIT;
+
+
+BEGIN;
+CREATE TABLE QRTZ_JOB_DETAILS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    JOB_NAME  VARCHAR(200) NOT NULL,
+    JOB_GROUP VARCHAR(200) NOT NULL,
+    DESCRIPTION VARCHAR(250) NULL,
+    JOB_CLASS_NAME   VARCHAR(250) NOT NULL,
+    IS_DURABLE VARCHAR(1) NOT NULL,
+    IS_NONCONCURRENT VARCHAR(1) NOT NULL,
+    IS_UPDATE_DATA VARCHAR(1) NOT NULL,
+    REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
+    JOB_DATA BLOB NULL,
+    PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
+);
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_TRIGGERS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    JOB_NAME  VARCHAR(200) NOT NULL,
+    JOB_GROUP VARCHAR(200) NOT NULL,
+    DESCRIPTION VARCHAR(250) NULL,
+    NEXT_FIRE_TIME BIGINT(13) NULL,
+    PREV_FIRE_TIME BIGINT(13) NULL,
+    PRIORITY INTEGER NULL,
+    TRIGGER_STATE VARCHAR(16) NOT NULL,
+    TRIGGER_TYPE VARCHAR(8) NOT NULL,
+    START_TIME BIGINT(13) NOT NULL,
+    END_TIME BIGINT(13) NULL,
+    CALENDAR_NAME VARCHAR(200) NULL,
+    MISFIRE_INSTR SMALLINT(2) NULL,
+    JOB_DATA BLOB NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
+        REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
+);
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_SIMPLE_TRIGGERS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    REPEAT_COUNT BIGINT(7) NOT NULL,
+    REPEAT_INTERVAL BIGINT(12) NOT NULL,
+    TIMES_TRIGGERED BIGINT(10) NOT NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_CRON_TRIGGERS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    CRON_EXPRESSION VARCHAR(200) NOT NULL,
+    TIME_ZONE_ID VARCHAR(80),
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_SIMPROP_TRIGGERS
+  (          
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    STR_PROP_1 VARCHAR(512) NULL,
+    STR_PROP_2 VARCHAR(512) NULL,
+    STR_PROP_3 VARCHAR(512) NULL,
+    INT_PROP_1 INT NULL,
+    INT_PROP_2 INT NULL,
+    LONG_PROP_1 BIGINT NULL,
+    LONG_PROP_2 BIGINT NULL,
+    DEC_PROP_1 NUMERIC(13,4) NULL,
+    DEC_PROP_2 NUMERIC(13,4) NULL,
+    BOOL_PROP_1 VARCHAR(1) NULL,
+    BOOL_PROP_2 VARCHAR(1) NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) 
+    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_BLOB_TRIGGERS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    BLOB_DATA BLOB NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_CALENDARS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    CALENDAR_NAME  VARCHAR(200) NOT NULL,
+    CALENDAR BLOB NOT NULL,
+    PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
+);
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_GROUP  VARCHAR(200) NOT NULL, 
+    PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
+);
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_FIRED_TRIGGERS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    ENTRY_ID VARCHAR(95) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    INSTANCE_NAME VARCHAR(200) NOT NULL,
+    FIRED_TIME BIGINT(13) NOT NULL,
+    SCHED_TIME BIGINT(13) NOT NULL,
+    PRIORITY INTEGER NOT NULL,
+    STATE VARCHAR(16) NOT NULL,
+    JOB_NAME VARCHAR(200) NULL,
+    JOB_GROUP VARCHAR(200) NULL,
+    IS_NONCONCURRENT VARCHAR(1) NULL,
+    REQUESTS_RECOVERY VARCHAR(1) NULL,
+    PRIMARY KEY (SCHED_NAME,ENTRY_ID)
+);
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_SCHEDULER_STATE
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    INSTANCE_NAME VARCHAR(200) NOT NULL,
+    LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
+    CHECKIN_INTERVAL BIGINT(13) NOT NULL,
+    PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
+);
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_LOCKS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    LOCK_NAME  VARCHAR(40) NOT NULL, 
+    PRIMARY KEY (SCHED_NAME,LOCK_NAME)
+);
+COMMIT;

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_mysql_innodb.sql
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_mysql_innodb.sql b/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_mysql_innodb.sql
new file mode 100644
index 0000000..c54493e
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_mysql_innodb.sql
@@ -0,0 +1,221 @@
+-- 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.
+
+--
+-- In your Quartz properties file, you'll need to set 
+-- org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
+--
+--
+-- By: Ron Cordell - roncordell
+-- I didn't see this anywhere, so I thought I'd post it here. This is the script from Quartz to create the tables in a MySQL database, modified to use INNODB instead of MYISAM.
+--
+
+BEGIN;
+DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
+DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
+DROP TABLE IF EXISTS QRTZ_LOCKS;
+DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
+DROP TABLE IF EXISTS QRTZ_CALENDARS;
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_JOB_DETAILS(
+SCHED_NAME VARCHAR(120) NOT NULL,
+JOB_NAME VARCHAR(200) NOT NULL,
+JOB_GROUP VARCHAR(200) NOT NULL,
+DESCRIPTION VARCHAR(250) NULL,
+JOB_CLASS_NAME VARCHAR(250) NOT NULL,
+IS_DURABLE VARCHAR(1) NOT NULL,
+IS_NONCONCURRENT VARCHAR(1) NOT NULL,
+IS_UPDATE_DATA VARCHAR(1) NOT NULL,
+REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
+JOB_DATA BLOB NULL,
+PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
+ENGINE=InnoDB;
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+JOB_NAME VARCHAR(200) NOT NULL,
+JOB_GROUP VARCHAR(200) NOT NULL,
+DESCRIPTION VARCHAR(250) NULL,
+NEXT_FIRE_TIME BIGINT(13) NULL,
+PREV_FIRE_TIME BIGINT(13) NULL,
+PRIORITY INTEGER NULL,
+TRIGGER_STATE VARCHAR(16) NOT NULL,
+TRIGGER_TYPE VARCHAR(8) NOT NULL,
+START_TIME BIGINT(13) NOT NULL,
+END_TIME BIGINT(13) NULL,
+CALENDAR_NAME VARCHAR(200) NULL,
+MISFIRE_INSTR SMALLINT(2) NULL,
+JOB_DATA BLOB NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
+REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
+ENGINE=InnoDB;
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+REPEAT_COUNT BIGINT(7) NOT NULL,
+REPEAT_INTERVAL BIGINT(12) NOT NULL,
+TIMES_TRIGGERED BIGINT(10) NOT NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_CRON_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+CRON_EXPRESSION VARCHAR(120) NOT NULL,
+TIME_ZONE_ID VARCHAR(80),
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_SIMPROP_TRIGGERS
+  (          
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    STR_PROP_1 VARCHAR(512) NULL,
+    STR_PROP_2 VARCHAR(512) NULL,
+    STR_PROP_3 VARCHAR(512) NULL,
+    INT_PROP_1 INT NULL,
+    INT_PROP_2 INT NULL,
+    LONG_PROP_1 BIGINT NULL,
+    LONG_PROP_2 BIGINT NULL,
+    DEC_PROP_1 NUMERIC(13,4) NULL,
+    DEC_PROP_2 NUMERIC(13,4) NULL,
+    BOOL_PROP_1 VARCHAR(1) NULL,
+    BOOL_PROP_2 VARCHAR(1) NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) 
+    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_BLOB_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+BLOB_DATA BLOB NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_CALENDARS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+CALENDAR_NAME VARCHAR(200) NOT NULL,
+CALENDAR BLOB NOT NULL,
+PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
+ENGINE=InnoDB;
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_FIRED_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+ENTRY_ID VARCHAR(95) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+INSTANCE_NAME VARCHAR(200) NOT NULL,
+FIRED_TIME BIGINT(13) NOT NULL,
+SCHED_TIME BIGINT(13) NOT NULL,
+PRIORITY INTEGER NOT NULL,
+STATE VARCHAR(16) NOT NULL,
+JOB_NAME VARCHAR(200) NULL,
+JOB_GROUP VARCHAR(200) NULL,
+IS_NONCONCURRENT VARCHAR(1) NULL,
+REQUESTS_RECOVERY VARCHAR(1) NULL,
+PRIMARY KEY (SCHED_NAME,ENTRY_ID))
+ENGINE=InnoDB;
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_SCHEDULER_STATE (
+SCHED_NAME VARCHAR(120) NOT NULL,
+INSTANCE_NAME VARCHAR(200) NOT NULL,
+LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
+CHECKIN_INTERVAL BIGINT(13) NOT NULL,
+PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
+ENGINE=InnoDB;
+COMMIT;
+
+BEGIN;
+CREATE TABLE QRTZ_LOCKS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+LOCK_NAME VARCHAR(40) NOT NULL,
+PRIMARY KEY (SCHED_NAME,LOCK_NAME))
+ENGINE=InnoDB;
+COMMIT;
+
+BEGIN;
+CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
+CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
+
+CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
+CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
+CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
+CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
+CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
+CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
+CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
+CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
+
+CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
+CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
+CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
+CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
+CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
+CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
+COMMIT;

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_oracle.sql
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_oracle.sql b/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_oracle.sql
new file mode 100644
index 0000000..4384ac5
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_oracle.sql
@@ -0,0 +1,208 @@
+-- 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.
+
+--
+-- A hint submitted by a user: Oracle DB MUST be created as "shared" and the 
+-- job_queue_processes parameter  must be greater than 2
+-- However, these settings are pretty much standard after any
+-- Oracle install, so most users need not worry about this.
+--
+-- Many other users (including the primary author of Quartz) have had success
+-- runing in dedicated mode, so only consider the above as a hint ;-)
+--
+
+delete from qrtz_fired_triggers;
+delete from qrtz_simple_triggers;
+delete from qrtz_simprop_triggers;
+delete from qrtz_cron_triggers;
+delete from qrtz_blob_triggers;
+delete from qrtz_triggers;
+delete from qrtz_job_details;
+delete from qrtz_calendars;
+delete from qrtz_paused_trigger_grps;
+delete from qrtz_locks;
+delete from qrtz_scheduler_state;
+
+drop table qrtz_calendars;
+drop table qrtz_fired_triggers;
+drop table qrtz_blob_triggers;
+drop table qrtz_cron_triggers;
+drop table qrtz_simple_triggers;
+drop table qrtz_simprop_triggers;
+drop table qrtz_triggers;
+drop table qrtz_job_details;
+drop table qrtz_paused_trigger_grps;
+drop table qrtz_locks;
+drop table qrtz_scheduler_state;
+
+
+CREATE TABLE qrtz_job_details
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    JOB_NAME  VARCHAR2(200) NOT NULL,
+    JOB_GROUP VARCHAR2(200) NOT NULL,
+    DESCRIPTION VARCHAR2(250) NULL,
+    JOB_CLASS_NAME   VARCHAR2(250) NOT NULL, 
+    IS_DURABLE VARCHAR2(1) NOT NULL,
+    IS_NONCONCURRENT VARCHAR2(1) NOT NULL,
+    IS_UPDATE_DATA VARCHAR2(1) NOT NULL,
+    REQUESTS_RECOVERY VARCHAR2(1) NOT NULL,
+    JOB_DATA BLOB NULL,
+    CONSTRAINT QRTZ_JOB_DETAILS_PK PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
+);
+CREATE TABLE qrtz_triggers
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    TRIGGER_NAME VARCHAR2(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR2(200) NOT NULL,
+    JOB_NAME  VARCHAR2(200) NOT NULL, 
+    JOB_GROUP VARCHAR2(200) NOT NULL,
+    DESCRIPTION VARCHAR2(250) NULL,
+    NEXT_FIRE_TIME NUMBER(13) NULL,
+    PREV_FIRE_TIME NUMBER(13) NULL,
+    PRIORITY NUMBER(13) NULL,
+    TRIGGER_STATE VARCHAR2(16) NOT NULL,
+    TRIGGER_TYPE VARCHAR2(8) NOT NULL,
+    START_TIME NUMBER(13) NOT NULL,
+    END_TIME NUMBER(13) NULL,
+    CALENDAR_NAME VARCHAR2(200) NULL,
+    MISFIRE_INSTR NUMBER(2) NULL,
+    JOB_DATA BLOB NULL,
+    CONSTRAINT QRTZ_TRIGGERS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    CONSTRAINT QRTZ_TRIGGER_TO_JOBS_FK FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP) 
+      REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP) 
+);
+CREATE TABLE qrtz_simple_triggers
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    TRIGGER_NAME VARCHAR2(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR2(200) NOT NULL,
+    REPEAT_COUNT NUMBER(7) NOT NULL,
+    REPEAT_INTERVAL NUMBER(12) NOT NULL,
+    TIMES_TRIGGERED NUMBER(10) NOT NULL,
+    CONSTRAINT QRTZ_SIMPLE_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    CONSTRAINT QRTZ_SIMPLE_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) 
+	REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+CREATE TABLE qrtz_cron_triggers
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    TRIGGER_NAME VARCHAR2(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR2(200) NOT NULL,
+    CRON_EXPRESSION VARCHAR2(120) NOT NULL,
+    TIME_ZONE_ID VARCHAR2(80),
+    CONSTRAINT QRTZ_CRON_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    CONSTRAINT QRTZ_CRON_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) 
+      REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+CREATE TABLE qrtz_simprop_triggers
+  (          
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    TRIGGER_NAME VARCHAR2(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR2(200) NOT NULL,
+    STR_PROP_1 VARCHAR2(512) NULL,
+    STR_PROP_2 VARCHAR2(512) NULL,
+    STR_PROP_3 VARCHAR2(512) NULL,
+    INT_PROP_1 NUMBER(10) NULL,
+    INT_PROP_2 NUMBER(10) NULL,
+    LONG_PROP_1 NUMBER(13) NULL,
+    LONG_PROP_2 NUMBER(13) NULL,
+    DEC_PROP_1 NUMERIC(13,4) NULL,
+    DEC_PROP_2 NUMERIC(13,4) NULL,
+    BOOL_PROP_1 VARCHAR2(1) NULL,
+    BOOL_PROP_2 VARCHAR2(1) NULL,
+    CONSTRAINT QRTZ_SIMPROP_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    CONSTRAINT QRTZ_SIMPROP_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) 
+      REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+CREATE TABLE qrtz_blob_triggers
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    TRIGGER_NAME VARCHAR2(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR2(200) NOT NULL,
+    BLOB_DATA BLOB NULL,
+    CONSTRAINT QRTZ_BLOB_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    CONSTRAINT QRTZ_BLOB_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) 
+        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+CREATE TABLE qrtz_calendars
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    CALENDAR_NAME  VARCHAR2(200) NOT NULL, 
+    CALENDAR BLOB NOT NULL,
+    CONSTRAINT QRTZ_CALENDARS_PK PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
+);
+CREATE TABLE qrtz_paused_trigger_grps
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    TRIGGER_GROUP  VARCHAR2(200) NOT NULL, 
+    CONSTRAINT QRTZ_PAUSED_TRIG_GRPS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
+);
+CREATE TABLE qrtz_fired_triggers 
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    ENTRY_ID VARCHAR2(95) NOT NULL,
+    TRIGGER_NAME VARCHAR2(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR2(200) NOT NULL,
+    INSTANCE_NAME VARCHAR2(200) NOT NULL,
+    FIRED_TIME NUMBER(13) NOT NULL,
+    SCHED_TIME NUMBER(13) NOT NULL,
+    PRIORITY NUMBER(13) NOT NULL,
+    STATE VARCHAR2(16) NOT NULL,
+    JOB_NAME VARCHAR2(200) NULL,
+    JOB_GROUP VARCHAR2(200) NULL,
+    IS_NONCONCURRENT VARCHAR2(1) NULL,
+    REQUESTS_RECOVERY VARCHAR2(1) NULL,
+    CONSTRAINT QRTZ_FIRED_TRIGGER_PK PRIMARY KEY (SCHED_NAME,ENTRY_ID)
+);
+CREATE TABLE qrtz_scheduler_state 
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    INSTANCE_NAME VARCHAR2(200) NOT NULL,
+    LAST_CHECKIN_TIME NUMBER(13) NOT NULL,
+    CHECKIN_INTERVAL NUMBER(13) NOT NULL,
+    CONSTRAINT QRTZ_SCHEDULER_STATE_PK PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
+);
+CREATE TABLE qrtz_locks
+  (
+    SCHED_NAME VARCHAR2(120) NOT NULL,
+    LOCK_NAME  VARCHAR2(40) NOT NULL, 
+    CONSTRAINT QRTZ_LOCKS_PK PRIMARY KEY (SCHED_NAME,LOCK_NAME)
+);
+
+create index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY);
+create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP);
+
+create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
+create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP);
+create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME);
+create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP);
+create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE);
+create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME);
+create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
+create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
+create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
+create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
+
+create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME);
+create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
+create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
+create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP);
+create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
+create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP);

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_postgres.sql
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_postgres.sql b/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_postgres.sql
new file mode 100644
index 0000000..9b7800f
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_postgres.sql
@@ -0,0 +1,204 @@
+-- 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.
+
+-- Thanks to Patrick Lightbody for submitting this...
+--
+-- In your Quartz properties file, you'll need to set 
+-- org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
+
+drop table qrtz_fired_triggers;
+DROP TABLE QRTZ_PAUSED_TRIGGER_GRPS;
+DROP TABLE QRTZ_SCHEDULER_STATE;
+DROP TABLE QRTZ_LOCKS;
+drop table qrtz_simple_triggers;
+drop table qrtz_cron_triggers;
+drop table qrtz_simprop_triggers;
+DROP TABLE QRTZ_BLOB_TRIGGERS;
+drop table qrtz_triggers;
+drop table qrtz_job_details;
+drop table qrtz_calendars;
+
+CREATE TABLE qrtz_job_details
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    JOB_NAME  VARCHAR(200) NOT NULL,
+    JOB_GROUP VARCHAR(200) NOT NULL,
+    DESCRIPTION VARCHAR(250) NULL,
+    JOB_CLASS_NAME   VARCHAR(250) NOT NULL, 
+    IS_DURABLE BOOL NOT NULL,
+    IS_NONCONCURRENT BOOL NOT NULL,
+    IS_UPDATE_DATA BOOL NOT NULL,
+    REQUESTS_RECOVERY BOOL NOT NULL,
+    JOB_DATA BYTEA NULL,
+    PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
+);
+
+CREATE TABLE qrtz_triggers
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    JOB_NAME  VARCHAR(200) NOT NULL, 
+    JOB_GROUP VARCHAR(200) NOT NULL,
+    DESCRIPTION VARCHAR(250) NULL,
+    NEXT_FIRE_TIME BIGINT NULL,
+    PREV_FIRE_TIME BIGINT NULL,
+    PRIORITY INTEGER NULL,
+    TRIGGER_STATE VARCHAR(16) NOT NULL,
+    TRIGGER_TYPE VARCHAR(8) NOT NULL,
+    START_TIME BIGINT NOT NULL,
+    END_TIME BIGINT NULL,
+    CALENDAR_NAME VARCHAR(200) NULL,
+    MISFIRE_INSTR SMALLINT NULL,
+    JOB_DATA BYTEA NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP) 
+	REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP) 
+);
+
+CREATE TABLE qrtz_simple_triggers
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    REPEAT_COUNT BIGINT NOT NULL,
+    REPEAT_INTERVAL BIGINT NOT NULL,
+    TIMES_TRIGGERED BIGINT NOT NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) 
+	REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+CREATE TABLE qrtz_cron_triggers
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    CRON_EXPRESSION VARCHAR(120) NOT NULL,
+    TIME_ZONE_ID VARCHAR(80),
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) 
+	REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+CREATE TABLE qrtz_simprop_triggers
+  (          
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    STR_PROP_1 VARCHAR(512) NULL,
+    STR_PROP_2 VARCHAR(512) NULL,
+    STR_PROP_3 VARCHAR(512) NULL,
+    INT_PROP_1 INT NULL,
+    INT_PROP_2 INT NULL,
+    LONG_PROP_1 BIGINT NULL,
+    LONG_PROP_2 BIGINT NULL,
+    DEC_PROP_1 NUMERIC(13,4) NULL,
+    DEC_PROP_2 NUMERIC(13,4) NULL,
+    BOOL_PROP_1 BOOL NULL,
+    BOOL_PROP_2 BOOL NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) 
+    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+CREATE TABLE qrtz_blob_triggers
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    BLOB_DATA BYTEA NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) 
+        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+);
+
+CREATE TABLE qrtz_calendars
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    CALENDAR_NAME  VARCHAR(200) NOT NULL, 
+    CALENDAR BYTEA NOT NULL,
+    PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
+);
+
+
+CREATE TABLE qrtz_paused_trigger_grps
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_GROUP  VARCHAR(200) NOT NULL, 
+    PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
+);
+
+CREATE TABLE qrtz_fired_triggers 
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    ENTRY_ID VARCHAR(95) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    INSTANCE_NAME VARCHAR(200) NOT NULL,
+    FIRED_TIME BIGINT NOT NULL,
+    SCHED_TIME BIGINT NOT NULL,
+    PRIORITY INTEGER NOT NULL,
+    STATE VARCHAR(16) NOT NULL,
+    JOB_NAME VARCHAR(200) NULL,
+    JOB_GROUP VARCHAR(200) NULL,
+    IS_NONCONCURRENT BOOL NULL,
+    REQUESTS_RECOVERY BOOL NULL,
+    PRIMARY KEY (SCHED_NAME,ENTRY_ID)
+);
+
+CREATE TABLE qrtz_scheduler_state 
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    INSTANCE_NAME VARCHAR(200) NOT NULL,
+    LAST_CHECKIN_TIME BIGINT NOT NULL,
+    CHECKIN_INTERVAL BIGINT NOT NULL,
+    PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
+);
+
+CREATE TABLE qrtz_locks
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    LOCK_NAME  VARCHAR(40) NOT NULL, 
+    PRIMARY KEY (SCHED_NAME,LOCK_NAME)
+);
+
+create index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY);
+create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP);
+
+create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
+create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP);
+create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME);
+create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP);
+create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE);
+create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME);
+create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
+create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
+create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
+create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
+
+create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME);
+create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
+create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
+create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP);
+create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
+create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP);
+
+
+commit;

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_sqlServer.sql
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_sqlServer.sql b/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_sqlServer.sql
new file mode 100644
index 0000000..288b990
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/resources/quartz/tables_sqlServer.sql
@@ -0,0 +1,296 @@
+-- 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.
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
+ALTER TABLE [dbo].[QRTZ_TRIGGERS] DROP CONSTRAINT FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS;
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
+ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] DROP CONSTRAINT FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS;
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
+ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] DROP CONSTRAINT FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS;
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
+ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] DROP CONSTRAINT FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS;
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_CALENDARS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_CALENDARS];
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_CRON_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_CRON_TRIGGERS];
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_BLOB_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_BLOB_TRIGGERS];
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_FIRED_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_FIRED_TRIGGERS];
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_PAUSED_TRIGGER_GRPS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS];
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SCHEDULER_STATE]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_SCHEDULER_STATE];
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_LOCKS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_LOCKS];
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_JOB_DETAILS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_JOB_DETAILS];
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SIMPLE_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS];
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SIMPROP_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS];
+
+IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
+DROP TABLE [dbo].[QRTZ_TRIGGERS];
+
+CREATE TABLE [dbo].[QRTZ_CALENDARS] (
+  [SCHED_NAME] [VARCHAR] (120)  NOT NULL ,
+  [CALENDAR_NAME] [VARCHAR] (200)  NOT NULL ,
+  [CALENDAR] [IMAGE] NOT NULL
+) ON [PRIMARY];
+
+CREATE TABLE [dbo].[QRTZ_CRON_TRIGGERS] (
+  [SCHED_NAME] [VARCHAR] (120)  NOT NULL ,
+  [TRIGGER_NAME] [VARCHAR] (200)  NOT NULL ,
+  [TRIGGER_GROUP] [VARCHAR] (200)  NOT NULL ,
+  [CRON_EXPRESSION] [VARCHAR] (120)  NOT NULL ,
+  [TIME_ZONE_ID] [VARCHAR] (80) 
+) ON [PRIMARY];
+
+CREATE TABLE [dbo].[QRTZ_FIRED_TRIGGERS] (
+  [SCHED_NAME] [VARCHAR] (120)  NOT NULL ,
+  [ENTRY_ID] [VARCHAR] (95)  NOT NULL ,
+  [TRIGGER_NAME] [VARCHAR] (200)  NOT NULL ,
+  [TRIGGER_GROUP] [VARCHAR] (200)  NOT NULL ,
+  [INSTANCE_NAME] [VARCHAR] (200)  NOT NULL ,
+  [FIRED_TIME] [BIGINT] NOT NULL ,
+  [SCHED_TIME] [BIGINT] NOT NULL ,
+  [PRIORITY] [INTEGER] NOT NULL ,
+  [STATE] [VARCHAR] (16)  NOT NULL,
+  [JOB_NAME] [VARCHAR] (200)  NULL ,
+  [JOB_GROUP] [VARCHAR] (200)  NULL ,
+  [IS_NONCONCURRENT] [VARCHAR] (1)  NULL ,
+  [REQUESTS_RECOVERY] [VARCHAR] (1)  NULL 
+) ON [PRIMARY];
+
+CREATE TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS] (
+  [SCHED_NAME] [VARCHAR] (120)  NOT NULL ,
+  [TRIGGER_GROUP] [VARCHAR] (200)  NOT NULL 
+) ON [PRIMARY];
+
+CREATE TABLE [dbo].[QRTZ_SCHEDULER_STATE] (
+  [SCHED_NAME] [VARCHAR] (120)  NOT NULL ,
+  [INSTANCE_NAME] [VARCHAR] (200)  NOT NULL ,
+  [LAST_CHECKIN_TIME] [BIGINT] NOT NULL ,
+  [CHECKIN_INTERVAL] [BIGINT] NOT NULL
+) ON [PRIMARY];
+
+CREATE TABLE [dbo].[QRTZ_LOCKS] (
+  [SCHED_NAME] [VARCHAR] (120)  NOT NULL ,
+  [LOCK_NAME] [VARCHAR] (40)  NOT NULL 
+) ON [PRIMARY];
+
+CREATE TABLE [dbo].[QRTZ_JOB_DETAILS] (
+  [SCHED_NAME] [VARCHAR] (120)  NOT NULL ,
+  [JOB_NAME] [VARCHAR] (200)  NOT NULL ,
+  [JOB_GROUP] [VARCHAR] (200)  NOT NULL ,
+  [DESCRIPTION] [VARCHAR] (250) NULL ,
+  [JOB_CLASS_NAME] [VARCHAR] (250)  NOT NULL ,
+  [IS_DURABLE] [VARCHAR] (1)  NOT NULL ,
+  [IS_NONCONCURRENT] [VARCHAR] (1)  NOT NULL ,
+  [IS_UPDATE_DATA] [VARCHAR] (1)  NOT NULL ,
+  [REQUESTS_RECOVERY] [VARCHAR] (1)  NOT NULL ,
+  [JOB_DATA] [IMAGE] NULL
+) ON [PRIMARY];
+
+CREATE TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] (
+  [SCHED_NAME] [VARCHAR] (120)  NOT NULL ,
+  [TRIGGER_NAME] [VARCHAR] (200)  NOT NULL ,
+  [TRIGGER_GROUP] [VARCHAR] (200)  NOT NULL ,
+  [REPEAT_COUNT] [BIGINT] NOT NULL ,
+  [REPEAT_INTERVAL] [BIGINT] NOT NULL ,
+  [TIMES_TRIGGERED] [BIGINT] NOT NULL
+) ON [PRIMARY];
+
+CREATE TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] (
+  [SCHED_NAME] [VARCHAR] (120)  NOT NULL ,
+  [TRIGGER_NAME] [VARCHAR] (200)  NOT NULL ,
+  [TRIGGER_GROUP] [VARCHAR] (200)  NOT NULL ,
+  [STR_PROP_1] [VARCHAR] (512) NULL,
+  [STR_PROP_2] [VARCHAR] (512) NULL,
+  [STR_PROP_3] [VARCHAR] (512) NULL,
+  [INT_PROP_1] [INT] NULL,
+  [INT_PROP_2] [INT] NULL,
+  [LONG_PROP_1] [BIGINT] NULL,
+  [LONG_PROP_2] [BIGINT] NULL,
+  [DEC_PROP_1] [NUMERIC] (13,4) NULL,
+  [DEC_PROP_2] [NUMERIC] (13,4) NULL,
+  [BOOL_PROP_1] [VARCHAR] (1) NULL,
+  [BOOL_PROP_2] [VARCHAR] (1) NULL,
+) ON [PRIMARY];
+
+CREATE TABLE [dbo].[QRTZ_BLOB_TRIGGERS] (
+  [SCHED_NAME] [VARCHAR] (120)  NOT NULL ,
+  [TRIGGER_NAME] [VARCHAR] (200)  NOT NULL ,
+  [TRIGGER_GROUP] [VARCHAR] (200)  NOT NULL ,
+  [BLOB_DATA] [IMAGE] NULL
+) ON [PRIMARY];
+
+CREATE TABLE [dbo].[QRTZ_TRIGGERS] (
+  [SCHED_NAME] [VARCHAR] (120)  NOT NULL ,
+  [TRIGGER_NAME] [VARCHAR] (200)  NOT NULL ,
+  [TRIGGER_GROUP] [VARCHAR] (200)  NOT NULL ,
+  [JOB_NAME] [VARCHAR] (200)  NOT NULL ,
+  [JOB_GROUP] [VARCHAR] (200)  NOT NULL ,
+  [DESCRIPTION] [VARCHAR] (250) NULL ,
+  [NEXT_FIRE_TIME] [BIGINT] NULL ,
+  [PREV_FIRE_TIME] [BIGINT] NULL ,
+  [PRIORITY] [INTEGER] NULL ,
+  [TRIGGER_STATE] [VARCHAR] (16)  NOT NULL ,
+  [TRIGGER_TYPE] [VARCHAR] (8)  NOT NULL ,
+  [START_TIME] [BIGINT] NOT NULL ,
+  [END_TIME] [BIGINT] NULL ,
+  [CALENDAR_NAME] [VARCHAR] (200)  NULL ,
+  [MISFIRE_INSTR] [SMALLINT] NULL ,
+  [JOB_DATA] [IMAGE] NULL
+) ON [PRIMARY];
+
+ALTER TABLE [dbo].[QRTZ_CALENDARS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_CALENDARS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [CALENDAR_NAME]
+  )  ON [PRIMARY];
+
+ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_CRON_TRIGGERS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  )  ON [PRIMARY];
+
+ALTER TABLE [dbo].[QRTZ_FIRED_TRIGGERS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_FIRED_TRIGGERS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [ENTRY_ID]
+  )  ON [PRIMARY];
+
+ALTER TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_PAUSED_TRIGGER_GRPS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [TRIGGER_GROUP]
+  )  ON [PRIMARY];
+
+ALTER TABLE [dbo].[QRTZ_SCHEDULER_STATE] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_SCHEDULER_STATE] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [INSTANCE_NAME]
+  )  ON [PRIMARY];
+
+ALTER TABLE [dbo].[QRTZ_LOCKS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_LOCKS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [LOCK_NAME]
+  )  ON [PRIMARY];
+
+ALTER TABLE [dbo].[QRTZ_JOB_DETAILS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_JOB_DETAILS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [JOB_NAME],
+    [JOB_GROUP]
+  )  ON [PRIMARY];
+
+ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_SIMPLE_TRIGGERS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  )  ON [PRIMARY];
+
+ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_SIMPROP_TRIGGERS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  )  ON [PRIMARY];
+
+ALTER TABLE [dbo].[QRTZ_TRIGGERS] WITH NOCHECK ADD
+  CONSTRAINT [PK_QRTZ_TRIGGERS] PRIMARY KEY  CLUSTERED
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  )  ON [PRIMARY];
+
+ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] ADD
+  CONSTRAINT [FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) REFERENCES [dbo].[QRTZ_TRIGGERS] (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) ON DELETE CASCADE;
+
+ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] ADD
+  CONSTRAINT [FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) REFERENCES [dbo].[QRTZ_TRIGGERS] (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) ON DELETE CASCADE;
+
+ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] ADD
+  CONSTRAINT [FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
+  (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) REFERENCES [dbo].[QRTZ_TRIGGERS] (
+    [SCHED_NAME],
+    [TRIGGER_NAME],
+    [TRIGGER_GROUP]
+  ) ON DELETE CASCADE;
+
+ALTER TABLE [dbo].[QRTZ_TRIGGERS] ADD
+  CONSTRAINT [FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS] FOREIGN KEY
+  (
+    [SCHED_NAME],
+    [JOB_NAME],
+    [JOB_GROUP]
+  ) REFERENCES [dbo].[QRTZ_JOB_DETAILS] (
+    [SCHED_NAME],
+    [JOB_NAME],
+    [JOB_GROUP]
+  );

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/resources/views.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/views.xml b/syncope620/server/persistence-jpa/src/main/resources/views.xml
new file mode 100644
index 0000000..2e029c8
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/resources/views.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+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.
+-->
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+  <comment>Views</comment>
+  <entry key="user_search">
+    CREATE VIEW user_search AS
+ 
+    SELECT u.id as subject_id, u.* FROM SyncopeUser u
+  </entry>
+  <entry key="user_search_unique_attr">
+    CREATE VIEW user_search_unique_attr AS
+
+    SELECT ua.owner_id AS subject_id,
+    ua.schema_name AS schema_name,
+    uav.booleanvalue AS booleanvalue,
+    uav.datevalue AS datevalue,
+    uav.doublevalue AS doublevalue,
+    uav.longvalue AS longvalue,
+    uav.stringvalue AS stringvalue
+    FROM UPlainAttrUniqueValue uav, UPlainAttr ua
+    WHERE uav.attribute_id = ua.id
+  </entry>
+  <entry key="user_search_attr">
+    CREATE VIEW user_search_attr AS
+
+    SELECT ua.owner_id AS subject_id,
+    ua.schema_name AS schema_name,
+    uav.booleanvalue AS booleanvalue,
+    uav.datevalue AS datevalue,
+    uav.doublevalue AS doublevalue,
+    uav.longvalue AS longvalue,
+    uav.stringvalue AS stringvalue
+    FROM UPlainAttrValue uav, UPlainAttr ua
+    WHERE uav.attribute_id = ua.id
+  </entry>
+  <entry key="user_search_null_attr">
+    CREATE VIEW user_search_null_attr AS
+
+    SELECT u.id AS subject_id,
+    UPlainSchema.name AS schema_name,
+    NULL AS booleanvalue,
+    NULL AS datevalue,
+    NULL AS doublevalue,
+    NULL AS longvalue,
+    NULL AS stringvalue
+    FROM SyncopeUser u CROSS JOIN UPlainSchema
+    LEFT OUTER JOIN UPlainAttr ua ON (UPlainSchema.name = ua.schema_name AND ua.owner_id = u.id)
+    WHERE ua.id IS NULL
+  </entry>
+  <entry key="user_search_membership">
+    CREATE VIEW user_search_membership AS
+
+    SELECT m.user_id AS subject_id, r.id AS role_id, r.name AS role_name
+    FROM Membership m, SyncopeRole r
+    WHERE m.role_id = r.id
+  </entry>
+  <entry key="user_search_resource">
+    CREATE VIEW user_search_resource AS
+
+    SELECT st.user_id AS subject_id, st.resource_name AS resource_name
+    FROM SyncopeUser_ExternalResource st
+  </entry>
+  <entry key="user_search_role_resource">
+    CREATE VIEW user_search_role_resource AS
+
+    SELECT m.user_id AS subject_id, st.resource_name AS resource_name
+    FROM Membership m, SyncopeRole r, SyncopeRole_ExternalResource st
+    WHERE m.role_id = r.id AND st.role_id = r.id
+  </entry>
+  <entry key="role_search">
+    CREATE VIEW role_search AS
+ 
+    SELECT r.id as subject_id, r.* FROM SyncopeRole r
+  </entry>
+  <entry key="role_search_unique_attr">
+    CREATE VIEW role_search_unique_attr AS
+
+    SELECT ra.owner_id AS subject_id,
+    rat.schema_name AS schema_name,
+    rav.booleanvalue AS booleanvalue,
+    rav.datevalue AS datevalue,
+    rav.doublevalue AS doublevalue,
+    rav.longvalue AS longvalue,
+    rav.stringvalue AS stringvalue
+    FROM RPlainAttrUniqueValue rav, RPlainAttr ra, RPlainAttrTemplate rat
+    WHERE rav.attribute_id = ra.id
+    AND ra.template_id = rat.id
+  </entry>
+  <entry key="role_search_attr">
+    CREATE VIEW role_search_attr AS
+
+    SELECT ra.owner_id AS subject_id,
+    rat.schema_name AS schema_name,
+    rav.booleanvalue AS booleanvalue,
+    rav.datevalue AS datevalue,
+    rav.doublevalue AS doublevalue,
+    rav.longvalue AS longvalue,
+    rav.stringvalue AS stringvalue
+    FROM RPlainAttrValue rav, RPlainAttr ra, RPlainAttrTemplate rat
+    WHERE rav.attribute_id = ra.id
+    AND ra.template_id = rat.id
+  </entry>
+  <entry key="role_search_null_attr">
+    CREATE VIEW role_search_null_attr AS
+
+    SELECT r.id AS subject_id,
+    RPlainSchema.name AS schema_name,
+    NULL AS booleanvalue,
+    NULL AS datevalue,
+    NULL AS doublevalue,
+    NULL AS longvalue,
+    NULL AS stringvalue
+    FROM SyncopeRole r CROSS JOIN RPlainSchema
+    LEFT OUTER JOIN RPlainAttr ra ON (ra.owner_id = r.id)
+    LEFT OUTER JOIN RPlainAttrTemplate rat ON (RPlainSchema.name = rat.schema_name AND ra.template_id = rat.id)
+    WHERE ra.id IS NULL
+  </entry>
+  <entry key="role_search_resource">
+    CREATE VIEW role_search_resource AS
+
+    SELECT st.role_id AS subject_id, st.resource_name AS resource_name
+    FROM SyncopeRole_ExternalResource st
+  </entry>
+  <entry key="role_search_entitlements">
+    CREATE VIEW role_search_entitlements AS
+
+    SELECT st.role_id AS subject_id, st.entitlement_name AS entitlement_name
+    FROM SyncopeRole_Entitlement st
+  </entry>
+
+</properties>

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/AbstractTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/AbstractTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/AbstractTest.java
new file mode 100644
index 0000000..b0fda7c
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/AbstractTest.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.persistence.jpa;
+
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { "classpath:persistenceTestEnv.xml" })
+public abstract class AbstractTest {
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/DummyConnectorRegistry.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/DummyConnectorRegistry.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/DummyConnectorRegistry.java
new file mode 100644
index 0000000..94c639c
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/DummyConnectorRegistry.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.persistence.jpa;
+
+import org.apache.syncope.persistence.api.dao.NotFoundException;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.provisioning.api.ConnectorRegistry;
+import org.springframework.stereotype.Component;
+
+@Component
+public class DummyConnectorRegistry implements ConnectorRegistry {
+
+    @Override
+    public void registerConnector(final ExternalResource resource)
+            throws NotFoundException {
+    }
+
+    @Override
+    public void unregisterConnector(final String id) {
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/TestInitializer.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/TestInitializer.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/TestInitializer.java
new file mode 100644
index 0000000..ec29345
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/TestInitializer.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.persistence.jpa;
+
+import org.apache.syncope.persistence.api.content.ContentLoader;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class TestInitializer implements InitializingBean {
+
+    @Autowired
+    private ContentLoader contentLoader;
+
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        contentLoader.load();
+    }
+
+}


[09/32] syncope git commit: Merge branch 'master' into 2_0_X

Posted by il...@apache.org.
Merge branch 'master' into 2_0_X


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

Branch: refs/heads/2_0_X
Commit: ea0ab200afc86bcd425cb3d3eacfd30c04f7627e
Parents: 553f10b 08893dc
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Sun Dec 28 14:51:50 2014 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Sun Dec 28 14:51:50 2014 +0100

----------------------------------------------------------------------
 installer/pom.xml                               |  20 +++
 .../installer/containers/jboss/JBoss.java       |  12 +-
 .../org/apache/syncope/installer/enums/DBs.java |   3 +
 .../installer/files/ConsoleProperties.java      |  31 ++++
 .../syncope/installer/files/CoreWebXml.java     |  76 ++------
 .../installer/files/GlassfishCoreWebXml.java    |  38 +---
 .../files/JBossDeploymentStructureXml.java      |  40 +----
 .../syncope/installer/files/ParentPom.java      | 176 +------------------
 .../files/PersistenceContextEMFactoryXml.java   |  47 +----
 .../installer/files/PersistenceProperties.java  |  27 +--
 .../installer/processes/ArchetypeProcess.java   |  41 +++--
 .../installer/processes/BaseProcess.java        |  54 ++++++
 .../installer/processes/ContainerProcess.java   | 171 ++++++++++++++----
 .../installer/processes/PersistenceProcess.java |  25 ++-
 .../installer/utilities/FileSystemUtils.java    |  45 +++++
 .../syncope/installer/utilities/MavenUtils.java |  31 +---
 .../src/main/resources/configuration.properties |  31 ++++
 .../main/resources/izpack/ProcessPanel.Spec.xml |  40 +++--
 installer/src/main/resources/izpack/install.xml |   6 +-
 .../main/resources/izpack/userInputLang.xml_eng |   4 +
 .../main/resources/izpack/userInputLang.xml_ita |   4 +
 .../src/main/resources/izpack/userInputSpec.xml |  20 ++-
 installer/src/main/resources/modelerPom.xml     | 116 ++++++++++++
 pom.xml                                         |   6 +-
 24 files changed, 592 insertions(+), 472 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/ea0ab200/installer/pom.xml
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/syncope/blob/ea0ab200/pom.xml
----------------------------------------------------------------------


[14/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/GuardedStringSerializer.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/GuardedStringSerializer.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/GuardedStringSerializer.java
new file mode 100644
index 0000000..8de59d4
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/GuardedStringSerializer.java
@@ -0,0 +1,90 @@
+/*
+ * 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.server.utils.serialization;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import org.identityconnectors.common.Base64;
+import org.identityconnectors.common.security.EncryptorFactory;
+import org.identityconnectors.common.security.GuardedString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class GuardedStringSerializer extends JsonSerializer<GuardedString> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(GuardedStringSerializer.class);
+
+    @Override
+    public void serialize(final GuardedString source, final JsonGenerator jgen, final SerializerProvider sp)
+            throws IOException, JsonProcessingException {
+
+        jgen.writeStartObject();
+
+        boolean readOnly = false;
+        try {
+            Field field = GuardedString.class.getDeclaredField("readOnly");
+            field.setAccessible(true);
+            readOnly = field.getBoolean(source);
+        } catch (Exception e) {
+            LOG.error("Could not get field value", e);
+        }
+        jgen.writeBooleanField("readOnly", readOnly);
+
+        boolean disposed = false;
+        try {
+            Field field = GuardedString.class.getDeclaredField("disposed");
+            field.setAccessible(true);
+            disposed = field.getBoolean(source);
+        } catch (Exception e) {
+            LOG.error("Could not get field value", e);
+        }
+        jgen.writeBooleanField("disposed", disposed);
+
+        final StringBuilder cleartext = new StringBuilder();
+        ((GuardedString) source).access(new GuardedString.Accessor() {
+
+            @Override
+            public void access(final char[] clearChars) {
+                cleartext.append(clearChars);
+            }
+        });
+        final byte[] encryptedBytes =
+                EncryptorFactory.getInstance().getDefaultEncryptor().encrypt(cleartext.toString().getBytes());
+        jgen.writeStringField("encryptedBytes", Base64.encode(encryptedBytes));
+
+        String base64SHA1Hash = null;
+        try {
+            Field field = GuardedString.class.getDeclaredField("base64SHA1Hash");
+            field.setAccessible(true);
+            base64SHA1Hash = field.get(source).toString();
+        } catch (Exception e) {
+            LOG.error("Could not get field value", e);
+        }
+        if (base64SHA1Hash != null) {
+            jgen.writeStringField("base64SHA1Hash", base64SHA1Hash);
+        }
+
+        jgen.writeEndObject();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/POJOHelper.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/POJOHelper.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/POJOHelper.java
new file mode 100644
index 0000000..fb9a888
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/POJOHelper.java
@@ -0,0 +1,80 @@
+/*
+ * 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.server.utils.serialization;
+
+import com.fasterxml.jackson.core.Version;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
+import org.identityconnectors.common.security.GuardedString;
+import org.identityconnectors.framework.common.objects.Attribute;
+import org.identityconnectors.framework.common.objects.SyncToken;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Helper class for serialization and deserialization of configuration objects (POJOs) in JSON.
+ */
+public final class POJOHelper {
+
+    private static final Logger LOG = LoggerFactory.getLogger(POJOHelper.class);
+
+    private static final ObjectMapper MAPPER;
+
+    static {
+        SimpleModule pojoModule = new SimpleModule("POJOModule", new Version(1, 0, 0, null, null, null));
+        pojoModule.addSerializer(GuardedString.class, new GuardedStringSerializer());
+        pojoModule.addSerializer(Attribute.class, new AttributeSerializer());
+        pojoModule.addSerializer(SyncToken.class, new SyncTokenSerializer());
+        pojoModule.addDeserializer(GuardedString.class, new GuardedStringDeserializer());
+        pojoModule.addDeserializer(Attribute.class, new AttributeDeserializer());
+        pojoModule.addDeserializer(SyncToken.class, new SyncTokenDeserializer());
+
+        MAPPER = new ObjectMapper();
+        MAPPER.registerModule(pojoModule);
+        MAPPER.registerModule(new AfterburnerModule());
+    }
+
+    public static String serialize(final Object object) {
+        String result = null;
+
+        try {
+            result = MAPPER.writeValueAsString(object);
+        } catch (Exception e) {
+            LOG.error("During serialization", e);
+        }
+
+        return result;
+    }
+
+    public static <T extends Object> T deserialize(final String serialized, final Class<T> reference) {
+        T result = null;
+
+        try {
+            result = MAPPER.readValue(serialized, reference);
+        } catch (Exception e) {
+            LOG.error("During deserialization", e);
+        }
+
+        return result;
+    }
+
+    private POJOHelper() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/SyncTokenDeserializer.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/SyncTokenDeserializer.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/SyncTokenDeserializer.java
new file mode 100644
index 0000000..f0d19ec
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/SyncTokenDeserializer.java
@@ -0,0 +1,65 @@
+/*
+ * 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.server.utils.serialization;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import org.apache.commons.codec.binary.Base64;
+import org.identityconnectors.framework.common.objects.SyncToken;
+
+class SyncTokenDeserializer extends JsonDeserializer<SyncToken> {
+
+    @Override
+    public SyncToken deserialize(final JsonParser jp, final DeserializationContext ctx)
+            throws IOException, JsonProcessingException {
+
+        ObjectNode tree = jp.readValueAsTree();
+
+        Object value = null;
+        if (tree.has("value")) {
+            JsonNode node = tree.get("value");
+            value = node.isNull()
+                    ? null
+                    : node.isBoolean()
+                            ? node.asBoolean()
+                            : node.isDouble()
+                                    ? node.asDouble()
+                                    : node.isLong()
+                                            ? node.asLong()
+                                            : node.isInt()
+                                                    ? node.asInt()
+                                                    : node.asText();
+
+            if (value instanceof String) {
+                String base64 = (String) value;
+                if (Base64.isBase64(base64)) {
+                    value = Base64.decodeBase64(base64);
+                }
+            }
+        }
+
+        return new SyncToken(value);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/SyncTokenSerializer.java
----------------------------------------------------------------------
diff --git a/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/SyncTokenSerializer.java b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/SyncTokenSerializer.java
new file mode 100644
index 0000000..a9e1206
--- /dev/null
+++ b/syncope620/server/utils/src/main/java/org/apache/syncope/server/utils/serialization/SyncTokenSerializer.java
@@ -0,0 +1,58 @@
+/*
+ * 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.server.utils.serialization;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import java.io.IOException;
+import org.apache.commons.codec.binary.Base64;
+import org.identityconnectors.framework.common.objects.SyncToken;
+
+class SyncTokenSerializer extends JsonSerializer<SyncToken> {
+
+    @Override
+    public void serialize(final SyncToken source, final JsonGenerator jgen, final SerializerProvider sp)
+            throws IOException, JsonProcessingException {
+
+        jgen.writeStartObject();
+
+        jgen.writeFieldName("value");
+
+        if (source.getValue() == null) {
+            jgen.writeNull();
+        } else if (source.getValue() instanceof Boolean) {
+            jgen.writeBoolean((Boolean) source.getValue());
+        } else if (source.getValue() instanceof Double) {
+            jgen.writeNumber((Double) source.getValue());
+        } else if (source.getValue() instanceof Long) {
+            jgen.writeNumber((Long) source.getValue());
+        } else if (source.getValue() instanceof Integer) {
+            jgen.writeNumber((Integer) source.getValue());
+        } else if (source.getValue() instanceof byte[]) {
+            jgen.writeString(Base64.encodeBase64String((byte[]) source.getValue()));
+        } else {
+            jgen.writeString(source.getValue().toString());
+        }
+
+        jgen.writeEndObject();
+    }
+
+}


[19/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/AttrTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/AttrTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/AttrTest.java
new file mode 100644
index 0000000..7fa9642
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/AttrTest.java
@@ -0,0 +1,237 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.Random;
+import javax.validation.ValidationException;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.dao.PlainAttrDAO;
+import org.apache.syncope.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttr;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.user.UPlainSchema;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUPlainAttr;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUPlainAttrUniqueValue;
+import org.apache.syncope.server.security.Encryptor;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.crypto.codec.Base64;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class AttrTest extends AbstractTest {
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Autowired
+    private PlainAttrDAO plainAttrDAO;
+
+    @Autowired
+    private PlainSchemaDAO userSchemaDAO;
+
+    @Test
+    public void findById() {
+        UPlainAttr attribute = plainAttrDAO.find(100L, UPlainAttr.class);
+        assertNotNull("did not find expected attribute schema", attribute);
+        attribute = plainAttrDAO.find(104L, UPlainAttr.class);
+        assertNotNull("did not find expected attribute schema", attribute);
+    }
+
+    @Test
+    public void read() {
+        UPlainAttr attribute = plainAttrDAO.find(100L, UPlainAttr.class);
+        assertNotNull(attribute);
+        assertTrue(attribute.getValues().isEmpty());
+        assertNotNull(attribute.getUniqueValue());
+    }
+
+    @Test
+    public void save() throws ClassNotFoundException {
+        User user = userDAO.find(1L);
+
+        UPlainSchema emailSchema = userSchemaDAO.find("email", UPlainSchema.class);
+        assertNotNull(emailSchema);
+
+        UPlainAttr attribute = new JPAUPlainAttr();
+        attribute.setSchema(emailSchema);
+        attribute.setOwner(user);
+
+        Exception thrown = null;
+        try {
+            attribute.addValue("john.doe@gmail.com", JPAAttributableUtil.getInstance(AttributableType.USER));
+            attribute.addValue("mario.rossi@gmail.com", JPAAttributableUtil.getInstance(AttributableType.USER));
+        } catch (ValidationException e) {
+            thrown = e;
+        }
+        assertNull("no validation exception expected here ", thrown);
+
+        try {
+            attribute.addValue("http://www.apache.org", JPAAttributableUtil.getInstance(AttributableType.USER));
+        } catch (ValidationException e) {
+            thrown = e;
+        }
+        assertNotNull("validation exception expected here ", thrown);
+    }
+
+    @Test
+    public void saveWithEnum() throws ClassNotFoundException {
+        User user = userDAO.find(1L);
+
+        UPlainSchema gender = userSchemaDAO.find("gender", UPlainSchema.class);
+        assertNotNull(gender);
+        assertNotNull(gender.getType());
+        assertNotNull(gender.getEnumerationValues());
+
+        UPlainAttr attribute = new JPAUPlainAttr();
+        attribute.setSchema(gender);
+        attribute.setOwner(user);
+        user.addPlainAttr(attribute);
+
+        Exception thrown = null;
+
+        try {
+            attribute.addValue("A", JPAAttributableUtil.getInstance(AttributableType.USER));
+        } catch (ValidationException e) {
+            thrown = e;
+        }
+        assertNotNull("validation exception expected here ", thrown);
+
+        attribute.addValue("M", JPAAttributableUtil.getInstance(AttributableType.USER));
+
+        InvalidEntityException iee = null;
+        try {
+            userDAO.save(user);
+        } catch (InvalidEntityException e) {
+            iee = e;
+        }
+        assertNull(iee);
+    }
+
+    @Test
+    public void validateAndSave() {
+        User user = userDAO.find(1L);
+
+        final UPlainSchema emailSchema = userSchemaDAO.find("email", UPlainSchema.class);
+        assertNotNull(emailSchema);
+
+        final UPlainSchema fullnameSchema = userSchemaDAO.find("fullname", UPlainSchema.class);
+        assertNotNull(fullnameSchema);
+
+        UPlainAttr attribute = new JPAUPlainAttr();
+        attribute.setSchema(emailSchema);
+
+        UPlainAttrUniqueValue uauv = new JPAUPlainAttrUniqueValue();
+        uauv.setAttr(attribute);
+        uauv.setSchema(fullnameSchema);
+        uauv.setStringValue("a value");
+
+        attribute.setUniqueValue(uauv);
+
+        user.addPlainAttr(attribute);
+
+        InvalidEntityException iee = null;
+        try {
+            userDAO.save(user);
+            fail();
+        } catch (InvalidEntityException e) {
+            iee = e;
+        }
+        assertNotNull(iee);
+        // for attribute
+        assertTrue(iee.hasViolation(EntityViolationType.InvalidValueList));
+        // for uauv
+        assertTrue(iee.hasViolation(EntityViolationType.InvalidUPlainSchema));
+    }
+
+    @Test
+    public void saveWithEncrypted() throws Exception {
+        User user = userDAO.find(1L);
+
+        final UPlainSchema obscureSchema = userSchemaDAO.find("obscure", UPlainSchema.class);
+        assertNotNull(obscureSchema);
+        assertNotNull(obscureSchema.getSecretKey());
+        assertNotNull(obscureSchema.getCipherAlgorithm());
+
+        UPlainAttr attribute = new JPAUPlainAttr();
+        attribute.setSchema(obscureSchema);
+        attribute.addValue("testvalue", JPAAttributableUtil.getInstance(AttributableType.USER));
+        attribute.setOwner(user);
+        user.addPlainAttr(attribute);
+
+        userDAO.save(user);
+
+        UPlainAttr obscure = user.getPlainAttr("obscure");
+        assertNotNull(obscure);
+        assertEquals(1, obscure.getValues().size());
+        assertEquals(Encryptor.getInstance(obscureSchema.getSecretKey()).
+                encode("testvalue", obscureSchema.getCipherAlgorithm()), obscure.getValues().get(0).getStringValue());
+    }
+
+    @Test
+    public void saveWithBinary() throws UnsupportedEncodingException {
+        User user = userDAO.find(1L);
+
+        final UPlainSchema photoSchema = userSchemaDAO.find("photo", UPlainSchema.class);
+        assertNotNull(photoSchema);
+        assertNotNull(photoSchema.getMimeType());
+
+        final byte[] bytes = new byte[20];
+        new Random().nextBytes(bytes);
+        final String photoB64Value = new String(Base64.encode(bytes), SyncopeConstants.DEFAULT_ENCODING);
+
+        UPlainAttr attribute = new JPAUPlainAttr();
+        attribute.setSchema(photoSchema);
+        attribute.addValue(photoB64Value, JPAAttributableUtil.getInstance(AttributableType.USER));
+        attribute.setOwner(user);
+        user.addPlainAttr(attribute);
+
+        userDAO.save(user);
+
+        UPlainAttr obscure = user.getPlainAttr("photo");
+        assertNotNull(obscure);
+        assertEquals(1, obscure.getValues().size());
+        assertTrue(Arrays.equals(bytes, obscure.getValues().get(0).getBinaryValue()));
+    }
+
+    @Test
+    public void delete() {
+        UPlainAttr attribute = plainAttrDAO.find(104L, UPlainAttr.class);
+        String attrSchemaName = attribute.getSchema().getKey();
+
+        plainAttrDAO.delete(attribute.getKey(), UPlainAttr.class);
+
+        UPlainSchema schema = userSchemaDAO.find(attrSchemaName, UPlainSchema.class);
+        assertNotNull("user attribute schema deleted when deleting values", schema);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/AttributableSearchTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/AttributableSearchTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/AttributableSearchTest.java
new file mode 100644
index 0000000..b4217fc
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/AttributableSearchTest.java
@@ -0,0 +1,484 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.syncope.common.lib.types.SubjectType;
+import org.apache.syncope.persistence.api.RoleEntitlementUtil;
+import org.apache.syncope.persistence.api.dao.EntitlementDAO;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.dao.SubjectSearchDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.dao.search.AttributeCond;
+import org.apache.syncope.persistence.api.dao.search.MembershipCond;
+import org.apache.syncope.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.persistence.api.dao.search.ResourceCond;
+import org.apache.syncope.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.persistence.api.dao.search.SubjectCond;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.transaction.annotation.Transactional;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { "classpath:persistenceTestEnv.xml" })
+@Transactional
+public class AttributableSearchTest {
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Autowired
+    private RoleDAO roleDAO;
+
+    @Autowired
+    private SubjectSearchDAO searchDAO;
+
+    @Autowired
+    private EntitlementDAO entitlementDAO;
+
+    @Test
+    public void userMatch() {
+        User user = userDAO.find(1L);
+        assertNotNull(user);
+
+        MembershipCond membershipCond = new MembershipCond();
+        membershipCond.setRoleId(5L);
+
+        assertFalse(searchDAO.matches(user, SearchCond.getLeafCond(membershipCond), SubjectType.USER));
+
+        membershipCond.setRoleId(1L);
+
+        assertTrue(searchDAO.matches(user, SearchCond.getLeafCond(membershipCond), SubjectType.USER));
+    }
+
+    @Test
+    public void roleMatch() {
+        Role role = roleDAO.find(1L);
+        assertNotNull(role);
+
+        AttributeCond attrCond = new AttributeCond();
+        attrCond.setSchema("show");
+        attrCond.setType(AttributeCond.Type.ISNOTNULL);
+
+        assertTrue(searchDAO.matches(role, SearchCond.getLeafCond(attrCond), SubjectType.ROLE));
+    }
+
+    @Test
+    public void searchWithLikeCondition() {
+        AttributeCond fullnameLeafCond = new AttributeCond(AttributeCond.Type.LIKE);
+        fullnameLeafCond.setSchema("fullname");
+        fullnameLeafCond.setExpression("%o%");
+
+        MembershipCond membershipCond = new MembershipCond();
+        membershipCond.setRoleId(1L);
+
+        AttributeCond loginDateCond = new AttributeCond(AttributeCond.Type.EQ);
+        loginDateCond.setSchema("loginDate");
+        loginDateCond.setExpression("2009-05-26");
+
+        SearchCond subCond = SearchCond.getAndCond(SearchCond.getLeafCond(fullnameLeafCond), SearchCond.getLeafCond(
+                membershipCond));
+
+        assertTrue(subCond.isValid());
+
+        SearchCond cond = SearchCond.getAndCond(subCond, SearchCond.getLeafCond(loginDateCond));
+
+        assertTrue(cond.isValid());
+
+        List<User> users =
+                searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), cond, SubjectType.USER);
+        assertNotNull(users);
+        assertEquals(1, users.size());
+    }
+
+    @Test
+    public void searchWithNotCondition() {
+        AttributeCond fullnameLeafCond = new AttributeCond(AttributeCond.Type.EQ);
+        fullnameLeafCond.setSchema("fullname");
+        fullnameLeafCond.setExpression("Giuseppe Verdi");
+
+        SearchCond cond = SearchCond.getNotLeafCond(fullnameLeafCond);
+        assertTrue(cond.isValid());
+
+        List<User> users =
+                searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), cond, SubjectType.USER);
+        assertNotNull(users);
+        assertEquals(4, users.size());
+
+        Set<Long> ids = new HashSet<Long>(users.size());
+        for (User user : users) {
+            ids.add(user.getKey());
+        }
+        assertTrue(ids.contains(1L));
+        assertTrue(ids.contains(3L));
+    }
+
+    @Test
+    public void searchByBoolean() {
+        AttributeCond coolLeafCond = new AttributeCond(AttributeCond.Type.EQ);
+        coolLeafCond.setSchema("cool");
+        coolLeafCond.setExpression("true");
+
+        SearchCond cond = SearchCond.getLeafCond(coolLeafCond);
+        assertTrue(cond.isValid());
+
+        List<User> users =
+                searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), cond, SubjectType.USER);
+        assertNotNull(users);
+        assertEquals(1, users.size());
+
+        assertEquals(Long.valueOf(4L), users.get(0).getKey());
+    }
+
+    @Test
+    public void searchByPageAndSize() {
+        AttributeCond fullnameLeafCond = new AttributeCond(AttributeCond.Type.LIKE);
+        fullnameLeafCond.setSchema("fullname");
+        fullnameLeafCond.setExpression("%o%");
+
+        MembershipCond membershipCond = new MembershipCond();
+        membershipCond.setRoleId(1L);
+
+        AttributeCond loginDateCond = new AttributeCond(AttributeCond.Type.EQ);
+        loginDateCond.setSchema("loginDate");
+        loginDateCond.setExpression("2009-05-26");
+
+        SearchCond subCond = SearchCond.getAndCond(SearchCond.getLeafCond(fullnameLeafCond), SearchCond.getLeafCond(
+                membershipCond));
+
+        assertTrue(subCond.isValid());
+
+        SearchCond cond = SearchCond.getAndCond(subCond, SearchCond.getLeafCond(loginDateCond));
+
+        assertTrue(cond.isValid());
+
+        List<User> users = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+                cond, 1, 2, Collections.<OrderByClause>emptyList(),
+                SubjectType.USER);
+        assertNotNull(users);
+        assertEquals(1, users.size());
+
+        users = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+                cond, 2, 2, Collections.<OrderByClause>emptyList(),
+                SubjectType.USER);
+        assertNotNull(users);
+        assertTrue(users.isEmpty());
+    }
+
+    @Test
+    public void searchByMembership() {
+        MembershipCond membershipCond = new MembershipCond();
+        membershipCond.setRoleId(1L);
+
+        List<User> users = searchDAO.search(
+                RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), SearchCond.getLeafCond(membershipCond),
+                SubjectType.USER);
+        assertNotNull(users);
+        assertEquals(2, users.size());
+
+        membershipCond = new MembershipCond();
+        membershipCond.setRoleId(5L);
+
+        users = searchDAO.search(
+                RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), SearchCond.getNotLeafCond(membershipCond),
+                SubjectType.USER);
+        assertNotNull(users);
+        assertEquals(5, users.size());
+    }
+
+    @Test
+    public void searchByIsNull() {
+        AttributeCond coolLeafCond = new AttributeCond(AttributeCond.Type.ISNULL);
+        coolLeafCond.setSchema("cool");
+
+        List<User> users = searchDAO.search(
+                RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), SearchCond.getLeafCond(coolLeafCond),
+                SubjectType.USER);
+        assertNotNull(users);
+        assertEquals(4, users.size());
+
+        coolLeafCond = new AttributeCond(AttributeCond.Type.ISNOTNULL);
+        coolLeafCond.setSchema("cool");
+
+        users = searchDAO.search(
+                RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), SearchCond.getLeafCond(coolLeafCond),
+                SubjectType.USER);
+        assertNotNull(users);
+        assertEquals(1, users.size());
+    }
+
+    @Test
+    public void searchByResource() {
+        ResourceCond ws2 = new ResourceCond();
+        ws2.setResourceName("ws-target-resource-2");
+
+        ResourceCond ws1 = new ResourceCond();
+        ws1.setResourceName("ws-target-resource-list-mappings-2");
+
+        SearchCond searchCondition = SearchCond.getAndCond(SearchCond.getNotLeafCond(ws2), SearchCond.getLeafCond(ws1));
+
+        assertTrue(searchCondition.isValid());
+
+        List<User> users = searchDAO.search(
+                RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), searchCondition,
+                SubjectType.USER);
+
+        assertNotNull(users);
+        assertEquals(1, users.size());
+    }
+
+    @Test
+    public void searchByUsernameAndId() {
+        SubjectCond usernameLeafCond = new SubjectCond(SubjectCond.Type.EQ);
+        usernameLeafCond.setSchema("username");
+        usernameLeafCond.setExpression("rossini");
+
+        SubjectCond idRightCond = new SubjectCond(SubjectCond.Type.LT);
+        idRightCond.setSchema("id");
+        idRightCond.setExpression("2");
+
+        SearchCond searchCondition = SearchCond.getOrCond(SearchCond.getLeafCond(usernameLeafCond),
+                SearchCond.getLeafCond(idRightCond));
+
+        List<User> matchingUsers = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+                searchCondition, SubjectType.USER);
+
+        assertNotNull(matchingUsers);
+        assertEquals(1, matchingUsers.size());
+        assertEquals("rossini", matchingUsers.iterator().next().getUsername());
+        assertEquals(1L, matchingUsers.iterator().next().getKey().longValue());
+    }
+
+    @Test
+    public void searchByRolenameAndId() {
+        SubjectCond rolenameLeafCond = new SubjectCond(SubjectCond.Type.EQ);
+        rolenameLeafCond.setSchema("name");
+        rolenameLeafCond.setExpression("root");
+
+        SubjectCond idRightCond = new SubjectCond(SubjectCond.Type.LT);
+        idRightCond.setSchema("id");
+        idRightCond.setExpression("2");
+
+        SearchCond searchCondition = SearchCond.getAndCond(SearchCond.getLeafCond(rolenameLeafCond),
+                SearchCond.getLeafCond(idRightCond));
+
+        assertTrue(searchCondition.isValid());
+
+        List<Role> matchingRoles = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+                searchCondition, SubjectType.ROLE);
+
+        assertNotNull(matchingRoles);
+        assertEquals(1, matchingRoles.size());
+        assertEquals("root", matchingRoles.iterator().next().getName());
+        assertEquals(1L, matchingRoles.iterator().next().getKey().longValue());
+    }
+
+    @Test
+    public void searchByUsernameAndFullname() {
+        SubjectCond usernameLeafCond = new SubjectCond(SubjectCond.Type.EQ);
+        usernameLeafCond.setSchema("username");
+        usernameLeafCond.setExpression("rossini");
+
+        AttributeCond idRightCond = new AttributeCond(AttributeCond.Type.LIKE);
+        idRightCond.setSchema("fullname");
+        idRightCond.setExpression("Giuseppe V%");
+
+        SearchCond searchCondition = SearchCond.getOrCond(SearchCond.getLeafCond(usernameLeafCond),
+                SearchCond.getLeafCond(idRightCond));
+
+        List<User> matchingUsers =
+                searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), searchCondition,
+                        SubjectType.USER);
+
+        assertNotNull(matchingUsers);
+        assertEquals(2, matchingUsers.size());
+    }
+
+    @Test
+    public void searchById() {
+        SubjectCond idLeafCond = new SubjectCond(SubjectCond.Type.LT);
+        idLeafCond.setSchema("id");
+        idLeafCond.setExpression("2");
+
+        SearchCond searchCondition = SearchCond.getLeafCond(idLeafCond);
+        assertTrue(searchCondition.isValid());
+
+        List<User> users =
+                searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), searchCondition,
+                        SubjectType.USER);
+
+        assertNotNull(users);
+        assertEquals(1, users.size());
+        assertEquals(1L, users.iterator().next().getKey().longValue());
+
+        idLeafCond = new SubjectCond(SubjectCond.Type.LT);
+        idLeafCond.setSchema("id");
+        idLeafCond.setExpression("4");
+
+        searchCondition = SearchCond.getNotLeafCond(idLeafCond);
+        assertTrue(searchCondition.isValid());
+
+        users = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), searchCondition,
+                SubjectType.USER);
+
+        assertNotNull(users);
+        assertEquals(2, users.size());
+        boolean found = false;
+        for (User user : users) {
+            if (user.getKey() == 4) {
+                found = true;
+            }
+        }
+        assertTrue(found);
+    }
+
+    @Test
+    public void userOrderBy() {
+        SubjectCond usernameLeafCond = new SubjectCond(SubjectCond.Type.EQ);
+        usernameLeafCond.setSchema("username");
+        usernameLeafCond.setExpression("rossini");
+        AttributeCond idRightCond = new AttributeCond(AttributeCond.Type.LIKE);
+        idRightCond.setSchema("fullname");
+        idRightCond.setExpression("Giuseppe V%");
+        SearchCond searchCondition = SearchCond.getOrCond(
+                SearchCond.getLeafCond(usernameLeafCond), SearchCond.getLeafCond(idRightCond));
+
+        List<OrderByClause> orderByClauses = new ArrayList<OrderByClause>();
+        OrderByClause orderByClause = new OrderByClause();
+        orderByClause.setField("username");
+        orderByClause.setDirection(OrderByClause.Direction.DESC);
+        orderByClauses.add(orderByClause);
+        orderByClause = new OrderByClause();
+        orderByClause.setField("fullname");
+        orderByClause.setDirection(OrderByClause.Direction.ASC);
+        orderByClauses.add(orderByClause);
+
+        List<User> users = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+                searchCondition, Collections.singletonList(orderByClause),
+                SubjectType.USER);
+        assertEquals(searchDAO.count(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+                searchCondition, SubjectType.USER),
+                users.size());
+    }
+
+    @Test
+    public void roleOrderBy() {
+        SubjectCond idLeafCond = new SubjectCond(SubjectCond.Type.LIKE);
+        idLeafCond.setSchema("name");
+        idLeafCond.setExpression("%r");
+        SearchCond searchCondition = SearchCond.getLeafCond(idLeafCond);
+        assertTrue(searchCondition.isValid());
+
+        OrderByClause orderByClause = new OrderByClause();
+        orderByClause.setField("name");
+
+        List<Role> roles = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+                searchCondition, Collections.singletonList(orderByClause), SubjectType.ROLE);
+        assertEquals(searchDAO.count(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+                searchCondition, SubjectType.ROLE),
+                roles.size());
+    }
+
+    @Test
+    public void issue202() {
+        ResourceCond ws2 = new ResourceCond();
+        ws2.setResourceName("ws-target-resource-2");
+
+        ResourceCond ws1 = new ResourceCond();
+        ws1.setResourceName("ws-target-resource-list-mappings-1");
+
+        SearchCond searchCondition =
+                SearchCond.getAndCond(SearchCond.getNotLeafCond(ws2), SearchCond.getNotLeafCond(ws1));
+        assertTrue(searchCondition.isValid());
+
+        List<User> users = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+                searchCondition, SubjectType.USER);
+        assertNotNull(users);
+        assertEquals(2, users.size());
+        boolean found = false;
+        for (User user : users) {
+            if (user.getKey() == 4) {
+                found = true;
+            }
+        }
+        assertTrue(found);
+    }
+
+    @Test
+    public void issue242() {
+        SubjectCond cond = new SubjectCond(AttributeCond.Type.LIKE);
+        cond.setSchema("id");
+        cond.setExpression("test%");
+
+        SearchCond searchCondition = SearchCond.getLeafCond(cond);
+        assertTrue(searchCondition.isValid());
+
+        List<User> users = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+                searchCondition, SubjectType.USER);
+        assertNotNull(users);
+        assertTrue(users.isEmpty());
+    }
+
+    @Test
+    public void issueSYNCOPE46() {
+        SubjectCond cond = new SubjectCond(AttributeCond.Type.LIKE);
+        cond.setSchema("username");
+        cond.setExpression("%ossin%");
+
+        SearchCond searchCondition = SearchCond.getLeafCond(cond);
+        assertTrue(searchCondition.isValid());
+
+        List<User> users = searchDAO.search(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()),
+                searchCondition, SubjectType.USER);
+        assertNotNull(users);
+        assertEquals(1, users.size());
+    }
+
+    @Test
+    public void issueSYNCOPE433() {
+        AttributeCond isNullCond = new AttributeCond(AttributeCond.Type.ISNULL);
+        isNullCond.setSchema("loginDate");
+
+        SubjectCond likeCond = new SubjectCond(AttributeCond.Type.LIKE);
+        likeCond.setSchema("username");
+        likeCond.setExpression("%ossin%");
+
+        SearchCond searchCond = SearchCond.getOrCond(
+                SearchCond.getLeafCond(isNullCond), SearchCond.getLeafCond(likeCond));
+
+        Integer count = searchDAO.count(RoleEntitlementUtil.getRoleIds(entitlementDAO.findAll()), searchCond,
+                SubjectType.USER);
+        assertNotNull(count);
+        assertTrue(count > 0);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/ConfTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/ConfTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/ConfTest.java
new file mode 100644
index 0000000..08d9919
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/ConfTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.dao.ConfDAO;
+import org.apache.syncope.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.persistence.api.entity.conf.CPlainAttr;
+import org.apache.syncope.persistence.api.entity.conf.CPlainSchema;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.conf.JPACPlainAttr;
+import org.apache.syncope.persistence.jpa.entity.conf.JPACPlainSchema;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class ConfTest extends AbstractTest {
+
+    @Autowired
+    private ConfDAO confDAO;
+
+    @Autowired
+    private PlainSchemaDAO plainSchemaDAO;
+
+    @Test
+    public void read() {
+        CPlainAttr conf = confDAO.find("selfRegistration.allowed");
+        assertNotNull(conf);
+        assertTrue(conf.getValues().get(0).getBooleanValue());
+
+        conf = confDAO.find("authentication.statuses");
+        assertNotNull(conf);
+        assertEquals(2, conf.getValues().size());
+
+        conf = confDAO.find("non.existing");
+        assertNull(conf);
+    }
+
+    @Test
+    public void setAndDelete() {
+        // 1. create CSChema
+        CPlainSchema useless = new JPACPlainSchema();
+        useless.setKey("useless");
+        useless.setType(AttrSchemaType.Date);
+        useless.setConversionPattern("yyyy-MM-dd");
+        useless = plainSchemaDAO.save(useless);
+
+        // 2. create conf
+        CPlainAttr newConf = new JPACPlainAttr();
+        newConf.setSchema(useless);
+        newConf.addValue("2014-06-20", JPAAttributableUtil.getInstance(AttributableType.CONFIGURATION));
+        confDAO.save(newConf);
+
+        CPlainAttr actual = confDAO.find("useless");
+        assertEquals(actual.getValuesAsStrings(), newConf.getValuesAsStrings());
+
+        // 3. update conf
+        newConf.getValues().clear();
+        newConf.addValue("2014-06-20", JPAAttributableUtil.getInstance(AttributableType.CONFIGURATION));
+        confDAO.save(newConf);
+
+        actual = confDAO.find("useless");
+        assertEquals(actual.getValuesAsStrings(), newConf.getValuesAsStrings());
+
+        // 4. delete conf
+        confDAO.delete("useless");
+        assertNull(confDAO.find("useless"));
+    }
+
+    @Test
+    public void issueSYNCOPE418() {
+        try {
+            CPlainSchema failing = new JPACPlainSchema();
+            failing.setKey("http://schemas.examples.org/security/authorization/organizationUnit");
+            failing.setType(AttrSchemaType.String);
+            plainSchemaDAO.save(failing);
+
+            fail();
+        } catch (InvalidEntityException e) {
+            assertTrue(e.hasViolation(EntityViolationType.InvalidName));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/ConnInstanceTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/ConnInstanceTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/ConnInstanceTest.java
new file mode 100644
index 0000000..95ce1a3
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/ConnInstanceTest.java
@@ -0,0 +1,145 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.syncope.common.lib.types.ConnConfPropSchema;
+import org.apache.syncope.common.lib.types.ConnConfProperty;
+import org.apache.syncope.persistence.api.dao.ConnInstanceDAO;
+import org.apache.syncope.persistence.api.entity.ConnInstance;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class ConnInstanceTest extends AbstractTest {
+
+    @Autowired
+    private ConnInstanceDAO connInstanceDAO;
+
+    @Test
+    public void findAll() {
+        List<ConnInstance> connectors = connInstanceDAO.findAll();
+        assertNotNull(connectors);
+        assertFalse(connectors.isEmpty());
+    }
+
+    @Test
+    public void findById() {
+        ConnInstance connectorInstance = connInstanceDAO.find(100L);
+
+        assertNotNull("findById did not work", connectorInstance);
+
+        assertEquals("invalid connector name",
+                "net.tirasa.connid.bundles.soap.WebServiceConnector", connectorInstance.getConnectorName());
+
+        assertEquals("invalid bundle name", "net.tirasa.connid.bundles.soap", connectorInstance.getBundleName());
+    }
+
+    @Test
+    public void save() throws ClassNotFoundException {
+        ConnInstance connInstance = new JPAConnInstance();
+
+        connInstance.setLocation(new File(System.getProperty("java.io.tmpdir")).toURI().toString());
+
+        // set connector version
+        connInstance.setVersion("1.0");
+
+        // set connector name
+        connInstance.setConnectorName("WebService");
+
+        // set bundle name
+        connInstance.setBundleName("org.apache.syncope.core.persistence.test.util");
+
+        connInstance.setDisplayName("New");
+
+        connInstance.setConnRequestTimeout(60);
+
+        // set the connector configuration using PropertyTO
+        Set<ConnConfProperty> conf = new HashSet<ConnConfProperty>();
+
+        ConnConfPropSchema endpointSchema = new ConnConfPropSchema();
+        endpointSchema.setName("endpoint");
+        endpointSchema.setType(String.class.getName());
+        endpointSchema.setRequired(true);
+        ConnConfProperty endpoint = new ConnConfProperty();
+        endpoint.setSchema(endpointSchema);
+        endpoint.getValues().add("http://host.domain");
+
+        ConnConfPropSchema servicenameSchema = new ConnConfPropSchema();
+        servicenameSchema.setName("servicename");
+        servicenameSchema.setType(String.class.getName());
+        servicenameSchema.setRequired(true);
+        ConnConfProperty servicename = new ConnConfProperty();
+        servicename.setSchema(servicenameSchema);
+        endpoint.getValues().add("Provisioning");
+
+        conf.add(endpoint);
+        conf.add(servicename);
+
+        // set connector configuration
+        connInstance.setConfiguration(conf);
+        assertFalse(connInstance.getConfiguration().isEmpty());
+
+        // perform save operation
+        ConnInstance actual = connInstanceDAO.save(connInstance);
+
+        assertNotNull("save did not work", actual.getKey());
+
+        assertTrue("save did not work", actual.getKey() > 100L);
+
+        assertEquals("save did not work for \"name\" attribute", "WebService", actual.getConnectorName());
+
+        assertEquals("save did not work for \"bundle name\" attribute", "org.apache.syncope.core.persistence.test.util",
+                actual.getBundleName());
+
+        assertEquals("save did not work for \"majorVersion\" attribute", "1.0", connInstance.getVersion());
+
+        assertEquals("New", actual.getDisplayName());
+
+        assertEquals(new Integer(60), actual.getConnRequestTimeout());
+
+        conf = connInstance.getConfiguration();
+        assertFalse(conf.isEmpty());
+
+        assertNotNull("configuration retrieving failed", conf);
+        assertTrue(conf.size() == 2);
+    }
+
+    @Test
+    public void delete() {
+        ConnInstance connectorInstance = connInstanceDAO.find(100L);
+        assertNotNull("find to delete did not work", connectorInstance);
+
+        connInstanceDAO.delete(connectorInstance.getKey());
+
+        ConnInstance actual = connInstanceDAO.find(100L);
+        assertNull("delete did not work", actual);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/DerAttrTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/DerAttrTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/DerAttrTest.java
new file mode 100644
index 0000000..bd76f3c
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/DerAttrTest.java
@@ -0,0 +1,280 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+import org.apache.syncope.persistence.api.dao.DerAttrDAO;
+import org.apache.syncope.persistence.api.dao.DerSchemaDAO;
+import org.apache.syncope.persistence.api.dao.MembershipDAO;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.entity.membership.MDerAttr;
+import org.apache.syncope.persistence.api.entity.membership.MDerAttrTemplate;
+import org.apache.syncope.persistence.api.entity.membership.MDerSchema;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttrValue;
+import org.apache.syncope.persistence.api.entity.membership.Membership;
+import org.apache.syncope.persistence.api.entity.role.RDerAttr;
+import org.apache.syncope.persistence.api.entity.role.RDerAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.RDerSchema;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttrValue;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.api.entity.user.UDerAttr;
+import org.apache.syncope.persistence.api.entity.user.UDerSchema;
+import org.apache.syncope.persistence.api.entity.user.UPlainAttrValue;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMDerAttr;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMDerAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMDerSchema;
+import org.apache.syncope.persistence.jpa.entity.role.JPARDerAttr;
+import org.apache.syncope.persistence.jpa.entity.role.JPARDerAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.role.JPARDerSchema;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUDerAttr;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUDerSchema;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class DerAttrTest extends AbstractTest {
+
+    @Autowired
+    private DerAttrDAO derAttrDAO;
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Autowired
+    private MembershipDAO membershipDAO;
+
+    @Autowired
+    private RoleDAO roleDAO;
+
+    @Autowired
+    private DerSchemaDAO derSchemaDAO;
+
+    @Test
+    public void findAll() {
+        List<UDerAttr> list = derAttrDAO.findAll(UDerAttr.class);
+        assertEquals("did not get expected number of derived attributes ", 2, list.size());
+    }
+
+    @Test
+    public void findById() {
+        UDerAttr attribute = derAttrDAO.find(100L, UDerAttr.class);
+        assertNotNull("did not find expected attribute schema", attribute);
+    }
+
+    @Test
+    public void saveUDerAttribute() {
+        UDerSchema cnSchema = derSchemaDAO.find("cn", UDerSchema.class);
+        assertNotNull(cnSchema);
+
+        User owner = userDAO.find(3L);
+        assertNotNull("did not get expected user", owner);
+
+        UDerAttr derAttr = new JPAUDerAttr();
+        derAttr.setOwner(owner);
+        derAttr.setSchema(cnSchema);
+
+        derAttr = derAttrDAO.save(derAttr);
+
+        UDerAttr actual = derAttrDAO.find(derAttr.getKey(), UDerAttr.class);
+        assertNotNull("expected save to work", actual);
+        assertEquals(derAttr, actual);
+
+        UPlainAttrValue firstname = owner.getPlainAttr("firstname").getValues().iterator().next();
+        UPlainAttrValue surname = owner.getPlainAttr("surname").getValues().iterator().next();
+
+        assertEquals(surname.getValue() + ", " + firstname.getValue(), derAttr.getValue(owner.getPlainAttrs()));
+    }
+
+    @Test
+    public void saveMDerAttribute() {
+        Membership owner = membershipDAO.find(1L);
+        assertNotNull("did not get expected user", owner);
+
+        MDerAttr derAttr = new JPAMDerAttr();
+        derAttr.setOwner(owner);
+        derAttr.setTemplate(owner.getRole().getAttrTemplate(MDerAttrTemplate.class, "mderiveddata"));
+
+        derAttr = derAttrDAO.save(derAttr);
+        assertNotNull(derAttr.getTemplate());
+
+        MDerAttr actual = derAttrDAO.find(derAttr.getKey(), MDerAttr.class);
+        assertNotNull("expected save to work", actual);
+        assertEquals(derAttr, actual);
+
+        MPlainAttrValue sx = owner.getPlainAttr("mderived_sx").getValues().iterator().next();
+        MPlainAttrValue dx = owner.getPlainAttr("mderived_dx").getValues().iterator().next();
+
+        assertEquals(sx.getValue() + "-" + dx.getValue(), derAttr.getValue(owner.getPlainAttrs()));
+    }
+
+    @Test
+    public void saveRDerAttribute() {
+        Role owner = roleDAO.find(1L);
+        assertNotNull("did not get expected user", owner);
+
+        RDerAttr derAttr = new JPARDerAttr();
+        derAttr.setOwner(owner);
+        derAttr.setTemplate(owner.getAttrTemplate(RDerAttrTemplate.class, "rderiveddata"));
+
+        derAttr = derAttrDAO.save(derAttr);
+        assertNotNull(derAttr.getTemplate());
+
+        RDerAttr actual = derAttrDAO.find(derAttr.getKey(), RDerAttr.class);
+        assertNotNull("expected save to work", actual);
+        assertEquals(derAttr, actual);
+
+        RPlainAttrValue sx = owner.getPlainAttr("rderived_sx").getValues().iterator().next();
+        RPlainAttrValue dx = owner.getPlainAttr("rderived_dx").getValues().iterator().next();
+
+        assertEquals(sx.getValue() + "-" + dx.getValue(), derAttr.getValue(owner.getPlainAttrs()));
+    }
+
+    @Test
+    public void delete() {
+        UDerAttr attribute = derAttrDAO.find(100L, UDerAttr.class);
+        String attributeSchemaName = attribute.getSchema().getKey();
+
+        derAttrDAO.delete(attribute.getKey(), UDerAttr.class);
+
+        UDerAttr actual = derAttrDAO.find(100L, UDerAttr.class);
+        assertNull("delete did not work", actual);
+
+        UDerSchema attributeSchema = derSchemaDAO.find(attributeSchemaName, UDerSchema.class);
+        assertNotNull("user derived attribute schema deleted " + "when deleting values", attributeSchema);
+    }
+
+    @Test
+    public void issueSYNCOPE134User() {
+        UDerSchema sderived = new JPAUDerSchema();
+        sderived.setKey("sderived");
+        sderived.setExpression("status + ' - ' + username + ' - ' + creationDate + '[' + failedLogins + ']'");
+
+        sderived = derSchemaDAO.save(sderived);
+        derSchemaDAO.flush();
+
+        UDerSchema actual = derSchemaDAO.find("sderived", UDerSchema.class);
+        assertNotNull("expected save to work", actual);
+        assertEquals(sderived, actual);
+
+        User owner = userDAO.find(3L);
+        assertNotNull("did not get expected user", owner);
+
+        UDerAttr derAttr = new JPAUDerAttr();
+        derAttr.setOwner(owner);
+        derAttr.setSchema(sderived);
+
+        derAttr = derAttrDAO.save(derAttr);
+        derAttrDAO.flush();
+
+        derAttr = derAttrDAO.find(derAttr.getKey(), UDerAttr.class);
+        assertNotNull("expected save to work", derAttr);
+
+        String value = derAttr.getValue(owner.getPlainAttrs());
+        assertNotNull(value);
+        assertFalse(value.isEmpty());
+        assertTrue(value.startsWith("active - vivaldi - 2010-10-20"));
+        assertTrue(value.endsWith("[0]"));
+    }
+
+    @Test
+    public void issueSYNCOPE134Role() {
+        RDerSchema sderived = new JPARDerSchema();
+        sderived.setKey("sderived");
+        sderived.setExpression("name");
+
+        sderived = derSchemaDAO.save(sderived);
+        derSchemaDAO.flush();
+
+        RDerSchema actual = derSchemaDAO.find("sderived", RDerSchema.class);
+        assertNotNull("expected save to work", actual);
+        assertEquals(sderived, actual);
+
+        Role owner = roleDAO.find(7L);
+        assertNotNull("did not get expected role", owner);
+
+        RDerAttrTemplate template = new JPARDerAttrTemplate();
+        template.setSchema(sderived);
+        owner.getAttrTemplates(RDerAttrTemplate.class).add(template);
+
+        RDerAttr derAttr = new JPARDerAttr();
+        derAttr.setOwner(owner);
+        derAttr.setTemplate(owner.getAttrTemplate(RDerAttrTemplate.class, sderived.getKey()));
+
+        derAttr = derAttrDAO.save(derAttr);
+        assertNotNull(derAttr.getTemplate());
+        derAttrDAO.flush();
+
+        derAttr = derAttrDAO.find(derAttr.getKey(), RDerAttr.class);
+        assertNotNull("expected save to work", derAttr);
+
+        String value = derAttr.getValue(owner.getPlainAttrs());
+        assertNotNull(value);
+        assertFalse(value.isEmpty());
+        assertTrue(value.startsWith("managingDirector"));
+    }
+
+    @Test
+    public void issueSYNCOPE134Memb() {
+        MDerSchema mderived = new JPAMDerSchema();
+        mderived.setKey("mderived");
+        mderived.setExpression("key");
+
+        mderived = derSchemaDAO.save(mderived);
+        derSchemaDAO.flush();
+
+        MDerSchema actual = derSchemaDAO.find("mderived", MDerSchema.class);
+        assertNotNull("expected save to work", actual);
+        assertEquals(mderived, actual);
+
+        Membership owner = membershipDAO.find(4L);
+        assertNotNull("did not get expected membership", owner);
+
+        MDerAttrTemplate template = new JPAMDerAttrTemplate();
+        template.setSchema(mderived);
+        owner.getRole().getAttrTemplates(MDerAttrTemplate.class).add(template);
+
+        derSchemaDAO.flush();
+
+        MDerAttr derAttr = new JPAMDerAttr();
+        derAttr.setOwner(owner);
+        derAttr.setTemplate(owner.getRole().getAttrTemplate(MDerAttrTemplate.class, mderived.getKey()));
+
+        derAttr = derAttrDAO.save(derAttr);
+        assertNotNull(derAttr.getTemplate());
+        derAttrDAO.flush();
+
+        derAttr = derAttrDAO.find(derAttr.getKey(), MDerAttr.class);
+        assertNotNull("expected save to work", derAttr);
+
+        String value = derAttr.getValue(owner.getPlainAttrs());
+        assertNotNull(value);
+        assertFalse(value.isEmpty());
+        assertTrue(value.equalsIgnoreCase("4"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/DerSchemaTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/DerSchemaTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/DerSchemaTest.java
new file mode 100644
index 0000000..0898114
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/DerSchemaTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.List;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.dao.DerSchemaDAO;
+import org.apache.syncope.persistence.api.entity.DerSchema;
+import org.apache.syncope.persistence.api.entity.role.RDerSchema;
+import org.apache.syncope.persistence.api.entity.user.UDerSchema;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUDerSchema;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class DerSchemaTest extends AbstractTest {
+
+    @Autowired
+    private DerSchemaDAO derSchemaDAO;
+
+    @Test
+    public void findAll() {
+        List<UDerSchema> list = derSchemaDAO.findAll(UDerSchema.class);
+        assertEquals(3, list.size());
+    }
+
+    @Test
+    public void findByName() {
+        UDerSchema attributeSchema = derSchemaDAO.find("cn", UDerSchema.class);
+        assertNotNull("did not find expected derived attribute schema", attributeSchema);
+    }
+
+    @Test
+    public void save() {
+        UDerSchema derivedAttributeSchema = new JPAUDerSchema();
+        derivedAttributeSchema.setKey("cn2");
+        derivedAttributeSchema.setExpression("firstname surname");
+
+        derSchemaDAO.save(derivedAttributeSchema);
+
+        UDerSchema actual = derSchemaDAO.find("cn2", UDerSchema.class);
+        assertNotNull("expected save to work", actual);
+        assertEquals(derivedAttributeSchema, actual);
+    }
+
+    @Test
+    public void delete() {
+        UDerSchema cn = derSchemaDAO.find("cn", UDerSchema.class);
+        assertNotNull(cn);
+
+        derSchemaDAO.delete(cn.getKey(), JPAAttributableUtil.getInstance(AttributableType.USER));
+
+        DerSchema actual = derSchemaDAO.find("cn", UDerSchema.class);
+        assertNull("delete did not work", actual);
+
+        // ------------- //
+        RDerSchema rderiveddata = derSchemaDAO.find("rderiveddata", RDerSchema.class);
+        assertNotNull(rderiveddata);
+
+        derSchemaDAO.delete(rderiveddata.getKey(), JPAAttributableUtil.getInstance(AttributableType.ROLE));
+
+        actual = derSchemaDAO.find("rderiveddata", RDerSchema.class);
+        assertNull("delete did not work", actual);
+    }
+
+    @Test
+    public void issueSYNCOPE418() {
+        UDerSchema schema = new JPAUDerSchema();
+        schema.setKey("http://schemas.examples.org/security/authorization/organizationUnit");
+
+        try {
+            derSchemaDAO.save(schema);
+            fail();
+        } catch (InvalidEntityException e) {
+            assertTrue(e.hasViolation(EntityViolationType.InvalidName));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/EntitlementTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/EntitlementTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/EntitlementTest.java
new file mode 100644
index 0000000..be13431
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/EntitlementTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.List;
+import org.apache.syncope.persistence.api.dao.EntitlementDAO;
+import org.apache.syncope.persistence.api.entity.Entitlement;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class EntitlementTest extends AbstractTest {
+
+    @Autowired
+    private EntitlementDAO entitlementDAO;
+
+    @Test
+    public void findAll() {
+        List<Entitlement> list = entitlementDAO.findAll();
+        assertEquals("did not get expected number of entitlements ", 86, list.size());
+    }
+
+    @Test
+    public void findByName() {
+        Entitlement entitlement = entitlementDAO.find("base");
+        assertNotNull("did not find expected entitlement", entitlement);
+    }
+
+    @Test
+    public void save() {
+        Entitlement entitlement = new JPAEntitlement();
+        entitlement.setKey("another");
+
+        entitlementDAO.save(entitlement);
+
+        Entitlement actual = entitlementDAO.find("another");
+        assertNotNull("expected save to work", actual);
+        assertEquals(entitlement, actual);
+    }
+
+    @Test
+    public void delete() {
+        Entitlement entitlement = entitlementDAO.find("base");
+        assertNotNull("did not find expected entitlement", entitlement);
+
+        entitlementDAO.delete("base");
+
+        assertNull(entitlementDAO.find("base"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/MembershipTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/MembershipTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/MembershipTest.java
new file mode 100644
index 0000000..53c6e6f
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/MembershipTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.List;
+import org.apache.syncope.persistence.api.dao.MembershipDAO;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.entity.membership.Membership;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMembership;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class MembershipTest extends AbstractTest {
+
+    @Autowired
+    private MembershipDAO membershipDAO;
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Autowired
+    private RoleDAO roleDAO;
+
+    @Test
+    public void findAll() {
+        List<Membership> list = membershipDAO.findAll();
+        assertEquals(7, list.size());
+    }
+
+    @Test
+    public void find() {
+        Membership membership = membershipDAO.find(1L);
+        assertNotNull("did not find expected membership", membership);
+    }
+
+    @Test
+    public void save() {
+        User user = userDAO.find(4L);
+        Role role = roleDAO.find(1L);
+
+        Membership membership = new JPAMembership();
+        membership.setUser(user);
+        membership.setRole(role);
+
+        membership = membershipDAO.save(membership);
+
+        Membership actual = membershipDAO.find(membership.getKey());
+        assertNotNull("expected save to work", actual);
+    }
+
+    @Test
+    public void delete() {
+        Membership membership = membershipDAO.find(4L);
+        membershipDAO.delete(membership.getKey());
+
+        Membership actual = membershipDAO.find(4L);
+        assertNull("delete did not work", actual);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/NotificationTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/NotificationTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/NotificationTest.java
new file mode 100644
index 0000000..859b63a
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/NotificationTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.List;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.persistence.api.dao.NotificationDAO;
+import org.apache.syncope.persistence.api.entity.Notification;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class NotificationTest extends AbstractTest {
+
+    @Autowired
+    private NotificationDAO notificationDAO;
+
+    @Test
+    public void find() {
+        Notification notification = notificationDAO.find(10L);
+        assertNotNull(notification);
+        assertNotNull(notification.getEvents());
+        assertFalse(notification.getEvents().isEmpty());
+        assertNotNull(notification.getUserAbout());
+        assertNotNull(notification.getRecipients());
+
+    }
+
+    @Test
+    public void findAll() {
+        List<Notification> notifications = notificationDAO.findAll();
+        assertNotNull(notifications);
+        assertFalse(notifications.isEmpty());
+    }
+
+    @Test
+    public void save() {
+        Notification notification = new JPANotification();
+        notification.addEvent("save");
+
+        notification.setUserAbout("fake search condition");
+
+        notification.setRecipients("fake search condition");
+
+        notification.setRecipientAttrName("email");
+        notification.setRecipientAttrType(IntMappingType.UserSchema);
+
+        notification.setSender("syncope@syncope.apache.org");
+        notification.setSubject("Test notification");
+        notification.setTemplate("test");
+
+        Notification actual = notificationDAO.save(notification);
+        assertNotNull(actual);
+        assertNotNull(actual.getKey());
+    }
+
+    @Test
+    public void delete() {
+        notificationDAO.delete(10L);
+        assertNull(notificationDAO.find(10L));
+    }
+
+    @Test
+    public void issueSYNCOPE445() {
+        Notification notification = new JPANotification();
+        notification.addEvent("save");
+
+        notification.setUserAbout("fake search condition");
+
+        notification.setRecipients("fake search condition");
+
+        notification.setRecipientAttrName("email");
+        notification.setRecipientAttrType(IntMappingType.UserSchema);
+
+        notification.addStaticRecipient("syncope445@syncope.apache.org");
+
+        notification.setSender("syncope@syncope.apache.org");
+        notification.setSubject("Test notification");
+        notification.setTemplate("test");
+
+        Notification actual = notificationDAO.save(notification);
+        assertNotNull(actual);
+        assertNotNull(actual.getKey());
+        assertNotNull(actual.getStaticRecipients());
+        assertFalse(actual.getStaticRecipients().isEmpty());
+    }
+
+    @Test
+    public void issueSYNCOPE446() {
+        Notification notification = new JPANotification();
+        notification.addEvent("[REST]:[RoleController]:[]:[create]:[SUCCESS]");
+
+        notification.setRoleAbout("fake search condition");
+
+        notification.setRecipientAttrName("email");
+        notification.setRecipientAttrType(IntMappingType.UserSchema);
+
+        notification.addStaticRecipient("syncope446@syncope.apache.org");
+
+        notification.setSender("syncope@syncope.apache.org");
+        notification.setSubject("Test notification");
+        notification.setTemplate("test");
+
+        Notification actual = notificationDAO.save(notification);
+        assertNotNull(actual);
+        assertNotNull(actual.getKey());
+        assertNotNull(actual.getStaticRecipients());
+        assertFalse(actual.getStaticRecipients().isEmpty());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/PlainSchemaTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/PlainSchemaTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/PlainSchemaTest.java
new file mode 100644
index 0000000..50d2ae9
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/PlainSchemaTest.java
@@ -0,0 +1,162 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.List;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttr;
+import org.apache.syncope.persistence.api.entity.role.RPlainSchema;
+import org.apache.syncope.persistence.api.entity.user.UPlainSchema;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.apache.syncope.persistence.jpa.entity.role.JPARPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUPlainSchema;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class PlainSchemaTest extends AbstractTest {
+
+    @Autowired
+    private PlainSchemaDAO plainSchemaDAO;
+
+    @Test
+    public void findAll() {
+        List<UPlainSchema> userList = plainSchemaDAO.findAll(UPlainSchema.class);
+        assertEquals(15, userList.size());
+
+        List<RPlainSchema> roleList = plainSchemaDAO.findAll(RPlainSchema.class);
+        assertEquals(5, roleList.size());
+    }
+
+    @Test
+    public void findByName() {
+        UPlainSchema schema = plainSchemaDAO.find("fullname", UPlainSchema.class);
+        assertNotNull("did not find expected attribute schema", schema);
+    }
+
+    @Test
+    public void findAttrs() {
+        List<RPlainSchema> schemas = plainSchemaDAO.findAll(RPlainSchema.class);
+        assertNotNull(schemas);
+        assertFalse(schemas.isEmpty());
+
+        for (RPlainSchema schema : schemas) {
+            List<RPlainAttr> attrs = plainSchemaDAO.findAttrs(schema, RPlainAttr.class);
+            assertNotNull(attrs);
+            assertFalse(attrs.isEmpty());
+        }
+    }
+
+    @Test
+    public void save() {
+        UPlainSchema schema = new JPAUPlainSchema();
+        schema.setKey("secondaryEmail");
+        schema.setType(AttrSchemaType.String);
+        schema.setValidatorClass("org.apache.syncope.core.validation.EmailAddressValidator");
+        schema.setMandatoryCondition("false");
+        schema.setMultivalue(true);
+
+        plainSchemaDAO.save(schema);
+
+        UPlainSchema actual = plainSchemaDAO.find("secondaryEmail", UPlainSchema.class);
+        assertNotNull("expected save to work", actual);
+        assertEquals(schema, actual);
+    }
+
+    @Test(expected = InvalidEntityException.class)
+    public void saveNonValid() {
+        UPlainSchema schema = new JPAUPlainSchema();
+        schema.setKey("secondaryEmail");
+        schema.setType(AttrSchemaType.String);
+        schema.setValidatorClass("org.apache.syncope.core.validation.EmailAddressValidator");
+        schema.setMandatoryCondition("false");
+        schema.setMultivalue(true);
+        schema.setUniqueConstraint(true);
+
+        plainSchemaDAO.save(schema);
+    }
+
+    @Test
+    public void checkForEnumType() {
+        RPlainSchema schema = new JPARPlainSchema();
+        schema.setType(AttrSchemaType.Enum);
+        schema.setKey("color");
+
+        Exception ex = null;
+        try {
+            plainSchemaDAO.save(schema);
+        } catch (Exception e) {
+            ex = e;
+        }
+        assertNotNull(ex);
+
+        schema.setEnumerationValues("red" + SyncopeConstants.ENUM_VALUES_SEPARATOR + "yellow");
+        schema.setEnumerationKeys("1" + SyncopeConstants.ENUM_VALUES_SEPARATOR + "2");
+
+        plainSchemaDAO.save(schema);
+
+        RPlainSchema actual = plainSchemaDAO.find(schema.getKey(), RPlainSchema.class);
+        assertNotNull(actual);
+        assertNotNull(actual.getEnumerationKeys());
+        assertFalse(actual.getEnumerationKeys().isEmpty());
+    }
+
+    @Test(expected = InvalidEntityException.class)
+    public void saveInvalidSchema() {
+        UPlainSchema schema = new JPAUPlainSchema();
+        schema.setKey("username");
+        plainSchemaDAO.save(schema);
+    }
+
+    @Test
+    public void delete() {
+        UPlainSchema fullnam = plainSchemaDAO.find("fullname", UPlainSchema.class);
+
+        plainSchemaDAO.delete(fullnam.getKey(), JPAAttributableUtil.getInstance(AttributableType.USER));
+
+        UPlainSchema actual = plainSchemaDAO.find("fullname", UPlainSchema.class);
+        assertNull("delete did not work", actual);
+    }
+
+    @Test
+    public void issueSYNCOPE418() {
+        UPlainSchema schema = new JPAUPlainSchema();
+        schema.setKey("http://schemas.examples.org/security/authorization/organizationUnit");
+
+        try {
+            plainSchemaDAO.save(schema);
+            fail();
+        } catch (InvalidEntityException e) {
+            assertTrue(e.hasViolation(EntityViolationType.InvalidName));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/PolicyTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/PolicyTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/PolicyTest.java
new file mode 100644
index 0000000..38c97a6
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/PolicyTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.List;
+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.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.dao.PolicyDAO;
+import org.apache.syncope.persistence.api.entity.PasswordPolicy;
+import org.apache.syncope.persistence.api.entity.Policy;
+import org.apache.syncope.persistence.api.entity.SyncPolicy;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class PolicyTest extends AbstractTest {
+
+    @Autowired
+    private PolicyDAO policyDAO;
+
+    @Test
+    public void findAll() {
+        List<Policy> policies = policyDAO.findAll();
+        assertNotNull(policies);
+        assertFalse(policies.isEmpty());
+    }
+
+    @Test
+    public void findById() {
+        Policy policy = policyDAO.find(1L);
+        assertNotNull("findById did not work", policy);
+    }
+
+    @Test
+    public void findByType() {
+        List<? extends Policy> policies = policyDAO.find(PolicyType.SYNC);
+        assertNotNull("findById did not work", policies);
+        assertFalse(policies.isEmpty());
+    }
+
+    @Test
+    public void findGlobalPasswordPolicy() {
+        PasswordPolicy policy = policyDAO.getGlobalPasswordPolicy();
+        assertNotNull("findById did not work", policy);
+
+        assertEquals(PolicyType.GLOBAL_PASSWORD, policy.getType());
+
+        assertEquals("invalid policy values", 8, (policy.getSpecification(PasswordPolicySpec.class)).getMinLength());
+    }
+
+    @Test(expected = InvalidEntityException.class)
+    public void saveInvalidPolicy() {
+        PasswordPolicySpec passwordPolicy = new PasswordPolicySpec();
+        passwordPolicy.setMaxLength(8);
+        passwordPolicy.setMinLength(6);
+
+        SyncPolicy policy = new JPASyncPolicy();
+        policy.setSpecification(passwordPolicy);
+        policy.setDescription("sync policy");
+
+        policyDAO.save(policy);
+    }
+
+    @Test(expected = InvalidEntityException.class)
+    public void saveSecondPasswordPolicy() {
+        PasswordPolicySpec passwordPolicy = new PasswordPolicySpec();
+        passwordPolicy.setMaxLength(8);
+        passwordPolicy.setMinLength(6);
+
+        PasswordPolicy policy = new JPAPasswordPolicy(true);
+        policy.setSpecification(passwordPolicy);
+        policy.setDescription("global password policy");
+
+        policyDAO.save(policy);
+    }
+
+    @Test
+    public void create() {
+        SyncPolicy policy = new JPASyncPolicy();
+
+        final String syncURuleName = "net.tirasa.sync.correlation.TirasaURule";
+        final String syncRRuleName = "net.tirasa.sync.correlation.TirasaRRule";
+
+        SyncPolicySpec syncPolicySpec = new SyncPolicySpec();
+        syncPolicySpec.setUserJavaRule(syncURuleName);
+        syncPolicySpec.setRoleJavaRule(syncRRuleName);
+
+        policy.setSpecification(syncPolicySpec);
+        policy.setDescription("Sync policy");
+
+        policy = policyDAO.save(policy);
+
+        assertNotNull(policy);
+        assertEquals(PolicyType.SYNC, policy.getType());
+        assertEquals(syncURuleName, (policy.getSpecification(SyncPolicySpec.class)).getUserJavaRule());
+        assertEquals(syncRRuleName, (policy.getSpecification(SyncPolicySpec.class)).getRoleJavaRule());
+    }
+
+    @Test
+    public void update() {
+        PasswordPolicySpec specification = new PasswordPolicySpec();
+        specification.setMaxLength(8);
+        specification.setMinLength(6);
+
+        Policy policy = policyDAO.getGlobalPasswordPolicy();
+        assertNotNull(policy);
+        policy.setSpecification(specification);
+
+        policy = policyDAO.save(policy);
+
+        assertNotNull(policy);
+        assertEquals(PolicyType.GLOBAL_PASSWORD, policy.getType());
+        assertEquals((policy.getSpecification(PasswordPolicySpec.class)).getMaxLength(), 8);
+        assertEquals((policy.getSpecification(PasswordPolicySpec.class)).getMinLength(), 6);
+    }
+
+    @Test
+    public void delete() {
+        Policy policy = policyDAO.find(1L);
+        assertNotNull("find to delete did not work", policy);
+
+        policyDAO.delete(policy);
+
+        Policy actual = policyDAO.find(1L);
+        assertNull("delete did not work", actual);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/ReportTest.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/ReportTest.java b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/ReportTest.java
new file mode 100644
index 0000000..0b97138
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/java/org/apache/syncope/persistence/jpa/entity/ReportTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.List;
+import org.apache.syncope.common.lib.report.UserReportletConf;
+import org.apache.syncope.persistence.api.dao.ReportDAO;
+import org.apache.syncope.persistence.api.entity.Report;
+import org.apache.syncope.persistence.jpa.AbstractTest;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class ReportTest extends AbstractTest {
+
+    @Autowired
+    private ReportDAO reportDAO;
+
+    @Test
+    public void find() {
+        Report report = reportDAO.find(1L);
+        assertNotNull(report);
+
+        report = reportDAO.find(10L);
+        assertNull(report);
+    }
+
+    @Test
+    public void findAll() {
+        List<Report> reports = reportDAO.findAll();
+        assertNotNull(reports);
+        assertEquals(1, reports.size());
+    }
+
+    @Test
+    public void save() {
+        int beforeCount = reportDAO.count();
+
+        Report report = new JPAReport();
+        report.setName("new report");
+        report.addReportletConf(new UserReportletConf("first"));
+        report.addReportletConf(new UserReportletConf("second"));
+
+        report = reportDAO.save(report);
+        assertNotNull(report);
+        assertNotNull(report.getKey());
+
+        int afterCount = reportDAO.count();
+        assertEquals(afterCount, beforeCount + 1);
+    }
+
+    @Test
+    public void delete() {
+        Report report = reportDAO.find(1L);
+        assertNotNull(report);
+
+        reportDAO.delete(1L);
+
+        report = reportDAO.find(1L);
+        assertNull(report);
+    }
+}


[31/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/RoleTO.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/RoleTO.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/RoleTO.java
new file mode 100644
index 0000000..79ddfb3
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/RoleTO.java
@@ -0,0 +1,258 @@
+/*
+ * 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.JsonIgnoreProperties;
+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 = "role")
+@XmlType
+@JsonIgnoreProperties({ "displayName" })
+public class RoleTO extends AbstractSubjectTO {
+
+    private static final long serialVersionUID = -7785920258290147542L;
+
+    private String name;
+
+    private long parent;
+
+    private Long userOwner;
+
+    private Long roleOwner;
+
+    private boolean inheritOwner;
+
+    private boolean inheritTemplates;
+
+    private boolean inheritAttrs;
+
+    private boolean inheritDerAttrs;
+
+    private boolean inheritVirAttrs;
+
+    private boolean inheritPasswordPolicy;
+
+    private boolean inheritAccountPolicy;
+
+    private final List<String> entitlements = new ArrayList<>();
+
+    private List<String> rAttrTemplates = new ArrayList<>();
+
+    private List<String> rDerAttrTemplates = new ArrayList<>();
+
+    private List<String> rVirAttrTemplates = new ArrayList<>();
+
+    private List<String> mAttrTemplates = new ArrayList<>();
+
+    private List<String> mDerAttrTemplates = new ArrayList<>();
+
+    private List<String> mVirAttrTemplates = new ArrayList<>();
+
+    private Long passwordPolicy;
+
+    private Long accountPolicy;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    public long getParent() {
+        return parent;
+    }
+
+    public void setParent(final long parent) {
+        this.parent = parent;
+    }
+
+    public Long getUserOwner() {
+        return userOwner;
+    }
+
+    public void setUserOwner(final Long userOwner) {
+        this.userOwner = userOwner;
+    }
+
+    public Long getRoleOwner() {
+        return roleOwner;
+    }
+
+    public void setRoleOwner(final Long roleOwner) {
+        this.roleOwner = roleOwner;
+    }
+
+    public boolean isInheritOwner() {
+        return inheritOwner;
+    }
+
+    public void setInheritOwner(final boolean inheritOwner) {
+        this.inheritOwner = inheritOwner;
+    }
+
+    public boolean isInheritTemplates() {
+        return inheritTemplates;
+    }
+
+    public void setInheritTemplates(boolean inheritTemplates) {
+        this.inheritTemplates = inheritTemplates;
+    }
+
+    public boolean isInheritAttrs() {
+        return inheritAttrs;
+    }
+
+    public void setInheritAttrs(final boolean inheritAttrs) {
+        this.inheritAttrs = inheritAttrs;
+    }
+
+    public boolean isInheritDerAttrs() {
+        return inheritDerAttrs;
+    }
+
+    public void setInheritDerAttrs(final boolean inheritDerAttrs) {
+        this.inheritDerAttrs = inheritDerAttrs;
+    }
+
+    public boolean isInheritVirAttrs() {
+        return inheritVirAttrs;
+    }
+
+    public void setInheritVirAttrs(final boolean inheritVirAttrs) {
+        this.inheritVirAttrs = inheritVirAttrs;
+    }
+
+    @XmlElementWrapper(name = "entitlements")
+    @XmlElement(name = "entitlement")
+    @JsonProperty("entitlements")
+    public List<String> getEntitlements() {
+        return entitlements;
+    }
+
+    @XmlElementWrapper(name = "rAttrTemplates")
+    @XmlElement(name = "rAttrTemplate")
+    @JsonProperty("rAttrTemplates")
+    public List<String> getRAttrTemplates() {
+        return rAttrTemplates;
+    }
+
+    @XmlElementWrapper(name = "rDerAttrTemplates")
+    @XmlElement(name = "rDerAttrTemplate")
+    @JsonProperty("rDerAttrTemplates")
+    public List<String> getRDerAttrTemplates() {
+        return rDerAttrTemplates;
+    }
+
+    @XmlElementWrapper(name = "rVirAttrTemplates")
+    @XmlElement(name = "rVirAttrTemplate")
+    @JsonProperty("rVirAttrTemplates")
+    public List<String> getRVirAttrTemplates() {
+        return rVirAttrTemplates;
+    }
+
+    @XmlElementWrapper(name = "mAttrTemplates")
+    @XmlElement(name = "mAttrTemplate")
+    @JsonProperty("mAttrTemplates")
+    public List<String> getMAttrTemplates() {
+        return mAttrTemplates;
+    }
+
+    @XmlElementWrapper(name = "mDerAttrTemplates")
+    @XmlElement(name = "mDerAttrTemplate")
+    @JsonProperty("mDerAttrTemplates")
+    public List<String> getMDerAttrTemplates() {
+        return mDerAttrTemplates;
+    }
+
+    @XmlElementWrapper(name = "mVirAttrTemplates")
+    @XmlElement(name = "mVirAttrTemplate")
+    @JsonProperty("mVirAttrTemplates")
+    public List<String> getMVirAttrTemplates() {
+        return mVirAttrTemplates;
+    }
+
+    public Long getPasswordPolicy() {
+        return passwordPolicy;
+    }
+
+    public void setPasswordPolicy(final Long passwordPolicy) {
+        this.passwordPolicy = passwordPolicy;
+    }
+
+    public boolean isInheritPasswordPolicy() {
+        return inheritPasswordPolicy;
+    }
+
+    /**
+     * Specify if password policy must be inherited. In this case eventual passwordPolicy occurrence will be ignored.
+     *
+     * @param inheritPasswordPolicy 'true' to inherit policy, false otherwise.
+     */
+    public void setInheritPasswordPolicy(final boolean inheritPasswordPolicy) {
+        this.inheritPasswordPolicy = inheritPasswordPolicy;
+    }
+
+    public Long getAccountPolicy() {
+        return accountPolicy;
+    }
+
+    public void setAccountPolicy(final Long accountPolicy) {
+        this.accountPolicy = accountPolicy;
+    }
+
+    public boolean isInheritAccountPolicy() {
+        return inheritAccountPolicy;
+    }
+
+    /**
+     * Specify if account policy must be inherited. In this case eventual accountPolicy occurrence will be ignored.
+     *
+     * @param inheritAccountPolicy 'true' to inherit policy, false otherwise.
+     */
+    public void setInheritAccountPolicy(final boolean inheritAccountPolicy) {
+        this.inheritAccountPolicy = inheritAccountPolicy;
+    }
+
+    public String getDisplayName() {
+        return getId() + " " + getName();
+    }
+
+    public static long fromDisplayName(final String displayName) {
+        long result = 0;
+        if (displayName != null && !displayName.isEmpty() && displayName.indexOf(' ') != -1) {
+            try {
+                result = Long.valueOf(displayName.split(" ")[0]);
+            } catch (NumberFormatException e) {
+                // just to avoid PMD warning about "empty catch block"
+                result = 0;
+            }
+        }
+
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
new file mode 100644
index 0000000..aceefe1
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
@@ -0,0 +1,183 @@
+/*
+ * 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.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+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.commons.lang3.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+@XmlRootElement(name = "user")
+@XmlType
+public class UserTO extends AbstractSubjectTO {
+
+    private static final long serialVersionUID = 7791304495192615740L;
+
+    private String password;
+
+    private final List<MembershipTO> memberships = new ArrayList<>();
+
+    private String status;
+
+    private String token;
+
+    private Date tokenExpireTime;
+
+    private String username;
+
+    private Date lastLoginDate;
+
+    private Date changePwdDate;
+
+    private Integer failedLogins;
+
+    private Long securityQuestion;
+
+    private String securityAnswer;
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(final String password) {
+        this.password = password;
+    }
+
+    @XmlElementWrapper(name = "memberships")
+    @XmlElement(name = "membership")
+    @JsonProperty("memberships")
+    public List<MembershipTO> getMemberships() {
+        return memberships;
+    }
+
+    @JsonIgnore
+    public Map<Long, MembershipTO> getMembershipMap() {
+        Map<Long, MembershipTO> result;
+
+        if (getMemberships() == null) {
+            result = Collections.emptyMap();
+        } else {
+            result = new HashMap<>(getMemberships().size());
+            for (MembershipTO membership : getMemberships()) {
+                result.put(membership.getRoleId(), membership);
+            }
+            result = Collections.unmodifiableMap(result);
+        }
+
+        return result;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(final String status) {
+        this.status = status;
+    }
+
+    public String getToken() {
+        return token;
+    }
+
+    public void setToken(final String token) {
+        this.token = token;
+    }
+
+    public Date getTokenExpireTime() {
+        return tokenExpireTime == null
+                ? null
+                : new Date(tokenExpireTime.getTime());
+    }
+
+    public void setTokenExpireTime(final Date tokenExpireTime) {
+        if (tokenExpireTime != null) {
+            this.tokenExpireTime = new Date(tokenExpireTime.getTime());
+        }
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(final String username) {
+        this.username = username;
+    }
+
+    public Date getChangePwdDate() {
+        return changePwdDate;
+    }
+
+    public Integer getFailedLogins() {
+        return failedLogins;
+    }
+
+    public Date getLastLoginDate() {
+        return lastLoginDate;
+    }
+
+    public void setChangePwdDate(final Date changePwdDate) {
+        this.changePwdDate = changePwdDate;
+    }
+
+    public void setFailedLogins(final Integer failedLogins) {
+        this.failedLogins = failedLogins;
+    }
+
+    public void setLastLoginDate(final Date lastLoginDate) {
+        this.lastLoginDate = lastLoginDate;
+    }
+
+    public Long getSecurityQuestion() {
+        return securityQuestion;
+    }
+
+    public void setSecurityQuestion(final Long securityQuestion) {
+        this.securityQuestion = securityQuestion;
+    }
+
+    public String getSecurityAnswer() {
+        return securityAnswer;
+    }
+
+    public void setSecurityAnswer(final String securityAnswer) {
+        this.securityAnswer = securityAnswer;
+    }
+
+    @Override
+    public String toString() {
+        return new ReflectionToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) {
+
+            @Override
+            protected boolean accept(final Field f) {
+                return super.accept(f) && !f.getName().equals("password");
+            }
+        }.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
index 2450c56..3394d05 100644
--- a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
@@ -24,37 +24,38 @@ import javax.xml.bind.annotation.XmlEnum;
 public enum EntityViolationType {
 
     Standard(""),
-    InvalidAccountPolicy("org.apache.syncope.core.validation.accountpolicy"),
-    InvalidConnInstanceLocation("org.apache.syncope.core.validation.conninstance.location"),
-    InvalidConnPoolConf("org.apache.syncope.core.validation.conninstance.poolConf"),
-    InvalidMapping("org.apache.syncope.core.validation.mapping"),
-    InvalidMSchema("org.apache.syncope.core.validation.attrvalue.mSchema"),
-    InvalidMDerSchema("org.apache.syncope.core.validation.attrvalue.mDerSchema"),
-    InvalidMVirSchema("org.apache.syncope.core.validation.attrvalue.mVirSchema"),
-    InvalidName("org.apache.syncope.core.validation.name"),
-    InvalidNotification("org.apache.syncope.core.validation.notification"),
-    InvalidPassword("org.apache.syncope.core.validation.syncopeuser.password"),
-    InvalidPasswordPolicy("org.apache.syncope.core.validation.passwordpolicy"),
-    InvalidPolicy("org.apache.syncope.core.validation.policy"),
-    InvalidPropagationTask("org.apache.syncope.core.validation.propagationtask"),
-    InvalidRSchema("org.apache.syncope.core.validation.attrvalue.rSchema"),
-    InvalidRDerSchema("org.apache.syncope.core.validation.attrvalue.rDerSchema"),
-    InvalidRVirSchema("org.apache.syncope.core.validation.attrvalue.rVirSchema"),
-    InvalidReport("org.apache.syncope.core.validation.report"),
-    InvalidResource("org.apache.syncope.core.validation.externalresource"),
-    InvalidRoleOwner("org.apache.syncope.core.validation.syncoperole.owner"),
-    InvalidSchemaEncrypted("org.apache.syncope.core.validation.schema.encrypted"),
-    InvalidSchemaEnum("org.apache.syncope.core.validation.schema.enum"),
-    InvalidSchemaMultivalueUnique("org.apache.syncope.core.validation.schema.multivalueUnique"),
-    InvalidSchedTask("org.apache.syncope.core.validation.schedtask"),
-    InvalidSyncTask("org.apache.syncope.core.validation.synctask"),
-    InvalidSyncPolicy("org.apache.syncope.core.validation.syncpolicy"),
-    InvalidUSchema("org.apache.syncope.core.validation.attrvalue.uSchema"),
-    InvalidUDerSchema("org.apache.syncope.core.validation.attrvalue.derSchema"),
-    InvalidUVirSchema("org.apache.syncope.core.validation.attrvalue.uVirSchema"),
-    InvalidUsername("org.apache.syncope.core.validation.syncopeuser.username"),
-    InvalidValueList("org.apache.syncope.core.validation.attr.valueList"),
-    MoreThanOneNonNull("org.apache.syncope.core.validation.attrvalue.moreThanOneNonNull");
+    InvalidAccountPolicy("org.apache.syncope.persistence.validation.accountpolicy"),
+    InvalidConnInstanceLocation("org.apache.syncope.persistence.validation.conninstance.location"),
+    InvalidConnPoolConf("org.apache.syncope.persistence.validation.conninstance.poolConf"),
+    InvalidCPlainSchema("org.apache.syncope.persistence.validation.attrvalue.cPlainSchema"),
+    InvalidMapping("org.apache.syncope.persistence.validation.mapping"),
+    InvalidMPlainSchema("org.apache.syncope.persistence.validation.attrvalue.mPlainSchema"),
+    InvalidMDerSchema("org.apache.syncope.persistence.validation.attrvalue.mDerSchema"),
+    InvalidMVirSchema("org.apache.syncope.persistence.validation.attrvalue.mVirSchema"),
+    InvalidName("org.apache.syncope.persistence.validation.name"),
+    InvalidNotification("org.apache.syncope.persistence.validation.notification"),
+    InvalidPassword("org.apache.syncope.persistence.validation.syncopeuser.password"),
+    InvalidPasswordPolicy("org.apache.syncope.persistence.validation.passwordpolicy"),
+    InvalidPolicy("org.apache.syncope.persistence.validation.policy"),
+    InvalidPropagationTask("org.apache.syncope.persistence.validation.propagationtask"),
+    InvalidRPlainSchema("org.apache.syncope.persistence.validation.attrvalue.rPlainSchema"),
+    InvalidRDerSchema("org.apache.syncope.persistence.validation.attrvalue.rDerSchema"),
+    InvalidRVirSchema("org.apache.syncope.persistence.validation.attrvalue.rVirSchema"),
+    InvalidReport("org.apache.syncope.persistence.validation.report"),
+    InvalidResource("org.apache.syncope.persistence.validation.externalresource"),
+    InvalidRoleOwner("org.apache.syncope.persistence.validation.syncoperole.owner"),
+    InvalidSchemaEncrypted("org.apache.syncope.persistence.validation.schema.encrypted"),
+    InvalidSchemaEnum("org.apache.syncope.persistence.validation.schema.enum"),
+    InvalidSchemaMultivalueUnique("org.apache.syncope.persistence.validation.schema.multivalueUnique"),
+    InvalidSchedTask("org.apache.syncope.persistence.validation.schedtask"),
+    InvalidSyncTask("org.apache.syncope.persistence.validation.synctask"),
+    InvalidSyncPolicy("org.apache.syncope.persistence.validation.syncpolicy"),
+    InvalidUPlainSchema("org.apache.syncope.persistence.validation.attrvalue.uPlainSchema"),
+    InvalidUDerSchema("org.apache.syncope.persistence.validation.attrvalue.derSchema"),
+    InvalidUVirSchema("org.apache.syncope.persistence.validation.attrvalue.uVirSchema"),
+    InvalidUsername("org.apache.syncope.persistence.validation.syncopeuser.username"),
+    InvalidValueList("org.apache.syncope.persistence.validation.attr.valueList"),
+    MoreThanOneNonNull("org.apache.syncope.persistence.validation.attrvalue.moreThanOneNonNull");
 
     private String message;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/types/PropagationTaskExecStatus.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/types/PropagationTaskExecStatus.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/types/PropagationTaskExecStatus.java
new file mode 100644
index 0000000..448b3a9
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/types/PropagationTaskExecStatus.java
@@ -0,0 +1,47 @@
+/*
+ * 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;
+
+/**
+ * Status of a propagation task execution.
+ *
+ * CREATED -&gt; SUBMITTED or UBSUBMITTED (depending on the external resource to
+ * return success or failure).
+ * SUBMITTED -&gt; SUCCESS or FAILURE (depending on the external resource to
+ * report success or failure).
+ */
+@XmlEnum
+public enum PropagationTaskExecStatus {
+
+    CREATED,
+    SUBMITTED,
+    UNSUBMITTED,
+    SUCCESS,
+    FAILURE;
+
+    public boolean isSuccessful() {
+        return this == SUCCESS || this == SUBMITTED;
+    }
+
+    public static PropagationTaskExecStatus fromString(final String value) {
+        return PropagationTaskExecStatus.valueOf(value.toUpperCase());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/types/TaskType.java
----------------------------------------------------------------------
diff --git a/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/types/TaskType.java b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/types/TaskType.java
new file mode 100644
index 0000000..a20d0a7
--- /dev/null
+++ b/syncope620/common/lib/src/main/java/org/apache/syncope/common/lib/types/TaskType.java
@@ -0,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.common.lib.types;
+
+import javax.xml.bind.annotation.XmlEnum;
+
+@XmlEnum
+public enum TaskType {
+
+    PROPAGATION("propagation"),
+    NOTIFICATION("notification"),
+    SCHEDULED("sched"),
+    SYNCHRONIZATION("sync"),
+    PUSH("push");
+
+    private String name;
+
+    private TaskType(final String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+
+    public static TaskType fromString(final String name) {
+        if (name != null) {
+            for (TaskType t : TaskType.values()) {
+                if (t.name.equalsIgnoreCase(name)) {
+                    return t;
+                }
+            }
+        }
+
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/pom.xml
----------------------------------------------------------------------
diff --git a/syncope620/pom.xml b/syncope620/pom.xml
index 368c76e..7587710 100644
--- a/syncope620/pom.xml
+++ b/syncope620/pom.xml
@@ -303,12 +303,47 @@ under the License.
     <syncope.version>${project.version}</syncope.version>
 
     <connid.version>1.4.0.0</connid.version>
+    <connid.soap.version>1.3.0</connid.soap.version>
+    <connid.db.table.version>2.2.0</connid.db.table.version>
+    <connid.csvdir.version>0.8</connid.csvdir.version>
+    <connid.ldap.version>1.4.0</connid.ldap.version>
+    <connid.ad.version>1.2.1</connid.ad.version>
 
     <jackson.version>2.4.4</jackson.version>
 
+    <spring.version>4.1.4.RELEASE</spring.version>
+    <spring-security.version>3.2.5.RELEASE</spring-security.version>
+
+    <openjpa.version>2.3.0</openjpa.version>
+    <commons-dbcp.version>2.0.1</commons-dbcp.version>
+    <hibernate-validator.version>5.1.3.Final</hibernate-validator.version>
+
+    <jasypt.version>1.9.2</jasypt.version>
+
+    <quartz.version>2.2.1</quartz.version>
+
+    <slf4j.version>1.7.9</slf4j.version>
     <log4j.version>2.1</log4j.version>
 
+    <commons-io.version>2.4</commons-io.version>
+    <commons-codec.version>1.10</commons-codec.version>
+    <commons-jexl.version>2.1.1</commons-jexl.version>
     <commons-lang.version>3.3.2</commons-lang.version>
+    <commons.logging.version>1.1.3</commons.logging.version>
+
+    <h2.version>1.4.184</h2.version>
+    <junit.version>4.12</junit.version>
+
+    <conf.directory>${project.build.directory}/test-classes</conf.directory>
+    <bundles.directory>${project.build.directory}/bundles</bundles.directory>
+    <connid.location>file:${bundles.directory}/</connid.location>
+    <log.directory>${project.build.directory}/log</log.directory>
+    <activiti-modeler.directory>${project.build.directory}/activiti-modeler</activiti-modeler.directory>
+    
+    <anonymousUser>anonymous</anonymousUser>
+    <!-- static keys, only used for build: generated overlays will override during archetype:generate -->
+    <anonymousKey>anonymousKey</anonymousKey>
+    <secretKey>1abcdefghilmnopqrstuvz2!</secretKey>
 
     <targetJdk>1.7</targetJdk>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -322,14 +357,109 @@ under the License.
         <artifactId>validation-api</artifactId>
         <version>1.1.0.Final</version>
       </dependency>
+      <dependency>
+        <groupId>org.apache.geronimo.specs</groupId>
+        <artifactId>geronimo-jpa_2.0_spec</artifactId>
+        <version>1.1</version> 
+      </dependency>
+      <dependency>
+        <groupId>javax.el</groupId>
+        <artifactId>javax.el-api</artifactId>
+        <version>3.0.0</version>
+        <scope>provided</scope>
+      </dependency>
       
       <dependency>
+        <groupId>org.apache.openjpa</groupId>
+        <artifactId>openjpa-jdbc</artifactId>
+        <version>${openjpa.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.openjpa</groupId>
+        <artifactId>openjpa-persistence-jdbc</artifactId>
+        <version>${openjpa.version}</version>
+      </dependency>
+
+      <dependency>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-dbcp2</artifactId>
+        <version>${commons-dbcp.version}</version>
+      </dependency>
+
+      <dependency>
+        <groupId>org.hibernate</groupId>
+        <artifactId>hibernate-validator</artifactId>
+        <version>${hibernate-validator.version}</version>
+      </dependency>
+            
+      <dependency>
+        <groupId>com.fasterxml.jackson.core</groupId>
+        <artifactId>jackson-core</artifactId>
+        <version>${jackson.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.fasterxml.jackson.core</groupId>
+        <artifactId>jackson-databind</artifactId>
+        <version>${jackson.version}</version>
+      </dependency>
+      <dependency>
         <groupId>com.fasterxml.jackson.core</groupId>
         <artifactId>jackson-annotations</artifactId>
         <version>${jackson.version}</version>
       </dependency>
+      <dependency>
+        <groupId>com.fasterxml.jackson.jaxrs</groupId>
+        <artifactId>jackson-jaxrs-json-provider</artifactId>
+        <version>${jackson.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.fasterxml.jackson.module</groupId>
+        <artifactId>jackson-module-afterburner</artifactId>
+        <version>${jackson.version}</version>
+      </dependency>
+            
+      <dependency>
+        <groupId>org.springframework</groupId>
+        <artifactId>spring-context</artifactId>
+        <version>${spring.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.springframework</groupId>
+        <artifactId>spring-tx</artifactId>
+        <version>${spring.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.springframework</groupId>
+        <artifactId>spring-jdbc</artifactId>
+        <version>${spring.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.springframework</groupId>
+        <artifactId>spring-orm</artifactId>
+        <version>${spring.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.springframework.security</groupId>
+        <artifactId>spring-security-core</artifactId>
+        <version>${spring-security.version}</version>
+      </dependency>
       
       <dependency>
+        <groupId>commons-io</groupId>
+        <artifactId>commons-io</artifactId>
+        <version>${commons-io.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>commons-codec</groupId>
+        <artifactId>commons-codec</artifactId>
+        <version>${commons-codec.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-jexl</artifactId>
+        <version>${commons-jexl.version}</version>
+      </dependency>
+      <dependency>
         <groupId>org.apache.commons</groupId>
         <artifactId>commons-lang3</artifactId>
         <version>${commons-lang.version}</version>
@@ -340,12 +470,64 @@ under the License.
         <artifactId>connector-framework</artifactId>
         <version>${connid.version}</version>
       </dependency>
+      <dependency>
+        <groupId>net.tirasa.connid</groupId>
+        <artifactId>connector-framework-internal</artifactId>
+        <version>${connid.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>net.tirasa.connid</groupId>
+        <artifactId>slf4j-logging</artifactId>
+        <version>${connid.version}</version>
+      </dependency>
       
       <dependency>
+        <groupId>com.h2database</groupId>
+        <artifactId>h2</artifactId>
+        <version>${h2.version}</version>
+      </dependency>
+      
+      <dependency>
+        <groupId>org.jasypt</groupId>
+        <artifactId>jasypt</artifactId>
+        <version>${jasypt.version}</version>
+      </dependency>
+      
+      <dependency>
+        <groupId>org.quartz-scheduler</groupId>
+        <artifactId>quartz</artifactId>
+        <version>${quartz.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>c3p0</groupId>
+            <artifactId>c3p0</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      
+      <dependency>
+        <groupId>org.slf4j</groupId>
+        <artifactId>slf4j-api</artifactId>
+        <version>${slf4j.version}</version>
+      </dependency>
+      <dependency>
         <groupId>org.apache.logging.log4j</groupId>
         <artifactId>log4j-api</artifactId>
         <version>${log4j.version}</version>
       </dependency>
+      
+      <dependency>
+        <groupId>org.springframework</groupId>
+        <artifactId>spring-test</artifactId>
+        <version>${spring.version}</version>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>junit</groupId>
+        <artifactId>junit</artifactId>
+        <version>${junit.version}</version>
+        <scope>test</scope>
+      </dependency>
     </dependencies>
 
   </dependencyManagement>
@@ -387,6 +569,30 @@ under the License.
             <!--<compilerArgument>-Xlint:unchecked</compilerArgument>-->
           </configuration>
         </plugin>
+        
+        <plugin>
+          <groupId>org.apache.openjpa</groupId>
+          <artifactId>openjpa-maven-plugin</artifactId>
+          <version>${openjpa.version}</version>
+        </plugin>
+        
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-surefire-plugin</artifactId>
+          <version>2.18</version>
+          <configuration>
+            <redirectTestOutputToFile>true</redirectTestOutputToFile>
+            <encoding>utf-8</encoding>
+            <runOrder>alphabetical</runOrder>
+            <argLine>-Xms512m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m</argLine>
+          </configuration>
+        </plugin>
+        
+        <plugin>
+          <groupId>org.codehaus.mojo</groupId>
+          <artifactId>exec-maven-plugin</artifactId>
+          <version>1.3.2</version>
+        </plugin>
       </plugins>
     </pluginManagement>
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/pom.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/pom.xml b/syncope620/server/persistence-api/pom.xml
index 5f88243..ff1d632 100644
--- a/syncope620/server/persistence-api/pom.xml
+++ b/syncope620/server/persistence-api/pom.xml
@@ -43,10 +43,18 @@ under the License.
       <groupId>net.tirasa.connid</groupId>
       <artifactId>connector-framework</artifactId>
     </dependency>
+    <dependency>
+      <groupId>net.tirasa.connid</groupId>
+      <artifactId>connector-framework-internal</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>net.tirasa.connid</groupId>
+      <artifactId>slf4j-logging</artifactId>
+    </dependency>
       
     <dependency>
       <groupId>org.apache.syncope.common</groupId>
-      <artifactId>syncope-lib</artifactId>
+      <artifactId>syncope-common-lib</artifactId>
       <version>${project.version}</version>
     </dependency>
   </dependencies>

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/RoleEntitlementUtil.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/RoleEntitlementUtil.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/RoleEntitlementUtil.java
new file mode 100644
index 0000000..4e65eb3
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/RoleEntitlementUtil.java
@@ -0,0 +1,88 @@
+/*
+ * 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.persistence.api;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+import org.apache.syncope.persistence.api.entity.Entitlement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Utility class for manipulating entitlements.
+ */
+public final class RoleEntitlementUtil {
+
+    private static final Pattern ROLE_ENTITLEMENT_NAME_PATTERN = Pattern.compile("^ROLE_([\\d])+");
+
+    private static final Logger LOG = LoggerFactory.getLogger(RoleEntitlementUtil.class);
+
+    public static String getEntitlementNameFromRoleId(final Long roleId) {
+        return "ROLE_" + roleId;
+    }
+
+    public static boolean isRoleEntitlement(final String entitlementName) {
+        return ROLE_ENTITLEMENT_NAME_PATTERN.matcher(entitlementName).matches();
+    }
+
+    public static Long getRoleId(final String entitlementName) {
+        Long result = null;
+
+        if (isRoleEntitlement(entitlementName)) {
+            try {
+                result = Long.valueOf(entitlementName.substring(entitlementName.indexOf('_') + 1));
+            } catch (Exception e) {
+                LOG.error("unable to parse {} to Long", entitlementName, e);
+            }
+        }
+
+        return result;
+    }
+
+    public static Set<Long> getRoleIds(final Set<String> entitlements) {
+        Set<Long> result = new HashSet<>();
+
+        for (String entitlement : entitlements) {
+            if (isRoleEntitlement(entitlement)) {
+                Long roleId = getRoleId(entitlement);
+                if (roleId != null) {
+                    result.add(roleId);
+                }
+            }
+        }
+
+        return result;
+    }
+
+    public static Set<Long> getRoleIds(final List<Entitlement> entitlements) {
+        Set<String> names = new HashSet<>(entitlements.size());
+        for (Entitlement entitlement : entitlements) {
+            names.add(entitlement.getKey());
+        }
+        return getRoleIds(names);
+    }
+
+    /**
+     * Private default constructor, for static-only classes.
+     */
+    private RoleEntitlementUtil() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/attrvalue/validation/InvalidEntityException.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/attrvalue/validation/InvalidEntityException.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/attrvalue/validation/InvalidEntityException.java
new file mode 100644
index 0000000..2822c21
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/attrvalue/validation/InvalidEntityException.java
@@ -0,0 +1,129 @@
+/*
+ * 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.persistence.api.attrvalue.validation;
+
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.validation.ConstraintViolation;
+import javax.validation.ValidationException;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+
+/**
+ * Exception thrown when any JPA entity fails bean validation.
+ */
+public class InvalidEntityException extends ValidationException {
+
+    private static final long serialVersionUID = 3249297275444409691L;
+
+    private final String entityClassSimpleName;
+
+    private final Map<Class<?>, Set<EntityViolationType>> violations = new HashMap<>();
+
+    /**
+     * Constructs a singleton map of violations from given parameters.
+     *
+     * @param entityClass class of invalid entity
+     * @param entityViolationType type of violation found
+     * @param message message to be associated to the violation
+     */
+    public InvalidEntityException(final Class<?> entityClass,
+            final EntityViolationType entityViolationType, final String message) {
+
+        super();
+
+        this.entityClassSimpleName = entityClass.getSimpleName();
+
+        entityViolationType.setMessage(message.trim());
+
+        this.violations.put(entityClass, EnumSet.noneOf(EntityViolationType.class));
+        this.violations.get(entityClass).add(entityViolationType);
+    }
+
+    /**
+     * Constructs a map of violations out of given <tt>ConstraintViolation</tt> set.
+     *
+     * @param entityClassSimpleName simple class name of invalid entity
+     * @param violations as returned by bean validation
+     */
+    public InvalidEntityException(final String entityClassSimpleName,
+            final Set<ConstraintViolation<Object>> violations) {
+
+        super();
+
+        this.entityClassSimpleName = entityClassSimpleName;
+
+        for (ConstraintViolation<Object> violation : violations) {
+            int firstComma = violation.getMessageTemplate().indexOf(';');
+
+            final String key = violation.getMessageTemplate().substring(
+                    0, firstComma > 0 ? firstComma : violation.getMessageTemplate().length());
+
+            final String message = violation.getMessageTemplate().substring(firstComma > 0 ? firstComma + 1 : 0);
+
+            EntityViolationType entityViolationType;
+
+            try {
+                entityViolationType = EntityViolationType.valueOf(key.trim());
+            } catch (IllegalArgumentException e) {
+                entityViolationType = EntityViolationType.Standard;
+            }
+
+            entityViolationType.setMessage(message.trim());
+
+            if (!this.violations.containsKey(violation.getLeafBean().getClass())) {
+                this.violations.put(violation.getLeafBean().getClass(), EnumSet.noneOf(EntityViolationType.class));
+            }
+
+            this.violations.get(violation.getLeafBean().getClass()).add(entityViolationType);
+        }
+    }
+
+    public final boolean hasViolation(final EntityViolationType type) {
+        boolean found = false;
+        for (Class<?> entity : violations.keySet()) {
+            if (violations.get(entity).contains(type)) {
+                found = true;
+            }
+        }
+
+        return found;
+    }
+
+    public String getEntityClassSimpleName() {
+        return entityClassSimpleName;
+    }
+
+    public final Map<Class<?>, Set<EntityViolationType>> getViolations() {
+        return violations;
+    }
+
+    @Override
+    public String getMessage() {
+        StringBuilder sb = new StringBuilder();
+
+        for (Class<?> entity : violations.keySet()) {
+            sb.append(entity.getSimpleName()).append(" ").append(violations.get(entity).toString()).append(", ");
+        }
+        sb.delete(sb.lastIndexOf(", "), sb.length());
+
+        return sb.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/attrvalue/validation/InvalidPlainAttrValueException.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/attrvalue/validation/InvalidPlainAttrValueException.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/attrvalue/validation/InvalidPlainAttrValueException.java
new file mode 100644
index 0000000..37466e3
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/attrvalue/validation/InvalidPlainAttrValueException.java
@@ -0,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.persistence.api.attrvalue.validation;
+
+import javax.validation.ValidationException;
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+
+public class InvalidPlainAttrValueException extends ValidationException {
+
+    private static final long serialVersionUID = -5023202610580202148L;
+
+    public InvalidPlainAttrValueException(final String errorMessage) {
+        super(errorMessage);
+    }
+
+    public InvalidPlainAttrValueException(final String errorMessage, final Throwable cause) {
+        super(errorMessage, cause);
+    }
+
+    public InvalidPlainAttrValueException(final PlainAttrValue value) {
+        this("Could not validate " + value.getValue());
+    }
+
+    public InvalidPlainAttrValueException(final PlainAttrValue value, Throwable cause) {
+        this("Could not validate " + value.getValue(), cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/attrvalue/validation/ParsingValidationException.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/attrvalue/validation/ParsingValidationException.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/attrvalue/validation/ParsingValidationException.java
new file mode 100644
index 0000000..efb1fd9
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/attrvalue/validation/ParsingValidationException.java
@@ -0,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.persistence.api.attrvalue.validation;
+
+import javax.validation.ValidationException;
+
+public class ParsingValidationException extends ValidationException {
+
+    private static final long serialVersionUID = 5669262895008285522L;
+
+    public ParsingValidationException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/attrvalue/validation/Validator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/attrvalue/validation/Validator.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/attrvalue/validation/Validator.java
new file mode 100644
index 0000000..bb88519
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/attrvalue/validation/Validator.java
@@ -0,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.persistence.api.attrvalue.validation;
+
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+
+public interface Validator {
+
+    void validate(String value, PlainAttrValue attrValue)
+            throws ParsingValidationException, InvalidPlainAttrValueException;
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/content/ContentExporter.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/content/ContentExporter.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/content/ContentExporter.java
new file mode 100644
index 0000000..25b0ecd
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/content/ContentExporter.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.persistence.api.content;
+
+import java.io.OutputStream;
+import javax.xml.transform.TransformerConfigurationException;
+import org.xml.sax.SAXException;
+
+public interface ContentExporter {
+
+    void export(OutputStream output, String wfTablePrefix) throws SAXException, TransformerConfigurationException;
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/content/ContentLoader.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/content/ContentLoader.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/content/ContentLoader.java
new file mode 100644
index 0000000..2f14027
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/content/ContentLoader.java
@@ -0,0 +1,25 @@
+/*
+ * 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.persistence.api.content;
+
+public interface ContentLoader {
+
+    void load();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/AttrTemplateDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/AttrTemplateDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/AttrTemplateDAO.java
index 85b00b4..e07c02c 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/AttrTemplateDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/AttrTemplateDAO.java
@@ -20,9 +20,9 @@ package org.apache.syncope.persistence.api.dao;
 
 import java.util.List;
 import org.apache.syncope.persistence.api.entity.AttrTemplate;
-import org.apache.syncope.persistence.api.entity.NormSchema;
+import org.apache.syncope.persistence.api.entity.Schema;
 
-public interface AttrTemplateDAO<K extends NormSchema> extends DAO<AttrTemplate<K>> {
+public interface AttrTemplateDAO<K extends Schema> extends DAO<AttrTemplate<K>, Long> {
 
     <T extends AttrTemplate<K>> T find(Long key, Class<T> reference);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ConfDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ConfDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ConfDAO.java
index 2b9d978..359c603 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ConfDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ConfDAO.java
@@ -18,18 +18,18 @@
  */
 package org.apache.syncope.persistence.api.dao;
 
-import org.apache.syncope.persistence.api.entity.conf.CNormAttr;
+import org.apache.syncope.persistence.api.entity.conf.CPlainAttr;
 import org.apache.syncope.persistence.api.entity.conf.Conf;
 
-public interface ConfDAO extends DAO<Conf> {
+public interface ConfDAO extends DAO<Conf, Long> {
 
-    CNormAttr find(String key);
+    CPlainAttr find(String key);
 
-    CNormAttr find(String key, String defaultValue);
+    CPlainAttr find(String key, String defaultValue);
 
     Conf get();
 
-    Conf save(CNormAttr attr);
+    Conf save(CPlainAttr attr);
 
     Conf delete(String key);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ConnInstanceDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ConnInstanceDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ConnInstanceDAO.java
new file mode 100644
index 0000000..90c10c4
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ConnInstanceDAO.java
@@ -0,0 +1,34 @@
+/*
+ * 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.persistence.api.dao;
+
+import java.util.List;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.entity.ConnInstance;
+
+public interface ConnInstanceDAO extends DAO<ConnInstance, Long> {
+
+    ConnInstance find(Long key);
+
+    List<ConnInstance> findAll();
+
+    ConnInstance save(ConnInstance connector) throws InvalidEntityException;
+
+    void delete(Long key);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DAO.java
index 54e9404..504f7e6 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DAO.java
@@ -20,11 +20,11 @@ package org.apache.syncope.persistence.api.dao;
 
 import org.apache.syncope.persistence.api.entity.Entity;
 
-public interface DAO<T extends Entity> {
+public interface DAO<E extends Entity<KEY>, KEY> {
 
-    void refresh(T entity);
+    void refresh(E entity);
 
-    void detach(T entity);
+    void detach(E entity);
 
     void flush();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DerAttrDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DerAttrDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DerAttrDAO.java
index 2c81734..5c8116b 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DerAttrDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DerAttrDAO.java
@@ -19,19 +19,18 @@
 package org.apache.syncope.persistence.api.dao;
 
 import java.util.List;
-import org.apache.syncope.persistence.api.dao.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
 import org.apache.syncope.persistence.api.entity.DerAttr;
-import org.apache.syncope.persistence.api.entity.NormAttr;
 
-public interface DerAttrDAO<K extends NormAttr> extends DAO<DerAttr<K>> {
+public interface DerAttrDAO extends DAO<DerAttr, Long> {
 
-    <T extends DerAttr<K>> T find(Long key, Class<T> reference);
+    <T extends DerAttr> T find(Long key, Class<T> reference);
 
-    <T extends DerAttr<K>> List<T> findAll(Class<T> reference);
+    <T extends DerAttr> List<T> findAll(Class<T> reference);
 
-    <T extends DerAttr<K>> T save(T derAttr) throws InvalidEntityException;
+    <T extends DerAttr> T save(T derAttr) throws InvalidEntityException;
 
-    <T extends DerAttr<K>> void delete(Long key, Class<T> reference);
+    <T extends DerAttr> void delete(Long key, Class<T> reference);
 
-    <T extends DerAttr<K>> void delete(T derAttr);
+    <T extends DerAttr> void delete(T derAttr);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DerSchemaDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DerSchemaDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DerSchemaDAO.java
index 3d39d38..46972a2 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DerSchemaDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DerSchemaDAO.java
@@ -19,19 +19,18 @@
 package org.apache.syncope.persistence.api.dao;
 
 import java.util.List;
-import org.apache.syncope.persistence.api.dao.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
 import org.apache.syncope.persistence.api.entity.AttributableUtil;
 import org.apache.syncope.persistence.api.entity.DerAttr;
 import org.apache.syncope.persistence.api.entity.DerSchema;
-import org.apache.syncope.persistence.api.entity.NormAttr;
 
-public interface DerSchemaDAO extends DAO<DerSchema> {
+public interface DerSchemaDAO extends DAO<DerSchema, String> {
 
     <T extends DerSchema> T find(String name, Class<T> reference);
 
     <T extends DerSchema> List<T> findAll(Class<T> reference);
 
-    <T extends DerAttr<K>, K extends NormAttr> List<T> findAttrs(DerSchema schema, Class<T> reference);
+    <T extends DerAttr> List<T> findAttrs(DerSchema schema, Class<T> reference);
 
     <T extends DerSchema> T save(T derSchema) throws InvalidEntityException;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/EntitlementDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/EntitlementDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/EntitlementDAO.java
index c38076e..8ca510b 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/EntitlementDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/EntitlementDAO.java
@@ -19,11 +19,11 @@
 package org.apache.syncope.persistence.api.dao;
 
 import java.util.List;
-import org.apache.syncope.persistence.api.dao.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
 import org.apache.syncope.persistence.api.entity.Entitlement;
 import org.apache.syncope.persistence.api.entity.role.Role;
 
-public interface EntitlementDAO extends DAO<Entitlement> {
+public interface EntitlementDAO extends DAO<Entitlement, String> {
 
     Entitlement find(String key);
 
@@ -31,7 +31,7 @@ public interface EntitlementDAO extends DAO<Entitlement> {
 
     Entitlement save(Entitlement entitlement) throws InvalidEntityException;
 
-    Entitlement saveEntitlementRole(Role role);
+    Entitlement saveRoleEntitlement(Role role);
 
     void delete(String key);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ExternalResourceDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ExternalResourceDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ExternalResourceDAO.java
index 3d03505..5b3d459 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ExternalResourceDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ExternalResourceDAO.java
@@ -21,12 +21,12 @@ package org.apache.syncope.persistence.api.dao;
 import java.util.List;
 import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.PolicyType;
-import org.apache.syncope.persistence.api.dao.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
 import org.apache.syncope.persistence.api.entity.ExternalResource;
 import org.apache.syncope.persistence.api.entity.MappingItem;
 import org.apache.syncope.persistence.api.entity.Policy;
 
-public interface ExternalResourceDAO extends DAO<ExternalResource> {
+public interface ExternalResourceDAO extends DAO<ExternalResource, String> {
 
     ExternalResource find(String key);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/LoggerDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/LoggerDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/LoggerDAO.java
index bcf0ac2..13808c3 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/LoggerDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/LoggerDAO.java
@@ -20,10 +20,10 @@ package org.apache.syncope.persistence.api.dao;
 
 import java.util.List;
 import org.apache.syncope.common.lib.types.LoggerType;
-import org.apache.syncope.persistence.api.dao.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
 import org.apache.syncope.persistence.api.entity.Logger;
 
-public interface LoggerDAO extends DAO<Logger> {
+public interface LoggerDAO extends DAO<Logger, String> {
 
     Logger find(String key);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/MembershipDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/MembershipDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/MembershipDAO.java
index a586aae..43412fe 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/MembershipDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/MembershipDAO.java
@@ -19,12 +19,12 @@
 package org.apache.syncope.persistence.api.dao;
 
 import java.util.List;
-import org.apache.syncope.persistence.api.dao.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
 import org.apache.syncope.persistence.api.entity.membership.Membership;
 import org.apache.syncope.persistence.api.entity.role.Role;
 import org.apache.syncope.persistence.api.entity.user.User;
 
-public interface MembershipDAO extends DAO<Membership> {
+public interface MembershipDAO extends DAO<Membership, Long> {
 
     Membership find(Long key);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/NormAttrDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/NormAttrDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/NormAttrDAO.java
deleted file mode 100644
index 2748c34..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/NormAttrDAO.java
+++ /dev/null
@@ -1,30 +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.persistence.api.dao;
-
-import org.apache.syncope.persistence.api.entity.NormAttr;
-
-public interface NormAttrDAO extends DAO<NormAttr> {
-
-    <T extends NormAttr> T find(Long key, Class<T> reference);
-
-    <T extends NormAttr> void delete(Long key, Class<T> reference);
-
-    <T extends NormAttr> void delete(T attr);
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/NormAttrValueDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/NormAttrValueDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/NormAttrValueDAO.java
deleted file mode 100644
index 4066913..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/NormAttrValueDAO.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.persistence.api.dao;
-
-import java.util.List;
-import org.apache.syncope.persistence.api.dao.validation.InvalidEntityException;
-import org.apache.syncope.persistence.api.entity.NormAttrValue;
-
-public interface NormAttrValueDAO extends DAO<NormAttrValue> {
-
-    <T extends NormAttrValue> T find(Long key, Class<T> reference);
-
-    <T extends NormAttrValue> List<T> findAll(Class<T> reference);
-
-    <T extends NormAttrValue> T save(T attributeValue) throws InvalidEntityException;
-
-    <T extends NormAttrValue> void delete(Long key, Class<T> reference);
-
-    <T extends NormAttrValue> void delete(T attributeValue);
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/NormSchemaDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/NormSchemaDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/NormSchemaDAO.java
deleted file mode 100644
index 88de3e1..0000000
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/NormSchemaDAO.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.persistence.api.dao;
-
-import java.util.List;
-import org.apache.syncope.persistence.api.dao.validation.InvalidEntityException;
-import org.apache.syncope.persistence.api.entity.AttributableUtil;
-import org.apache.syncope.persistence.api.entity.NormAttr;
-import org.apache.syncope.persistence.api.entity.NormSchema;
-
-public interface NormSchemaDAO extends DAO<NormSchema> {
-
-    <T extends NormSchema> T find(String key, Class<T> reference);
-
-    <T extends NormSchema> List<T> findAll(Class<T> reference);
-
-    <T extends NormAttr> List<T> findAttrs(NormSchema schema, Class<T> reference);
-
-    <T extends NormSchema> T save(T schema) throws InvalidEntityException;
-
-    void delete(String name, AttributableUtil attributableUtil);
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/NotificationDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/NotificationDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/NotificationDAO.java
index 3488303..fadb811 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/NotificationDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/NotificationDAO.java
@@ -19,10 +19,10 @@
 package org.apache.syncope.persistence.api.dao;
 
 import java.util.List;
-import org.apache.syncope.persistence.api.dao.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
 import org.apache.syncope.persistence.api.entity.Notification;
 
-public interface NotificationDAO extends DAO<Notification> {
+public interface NotificationDAO extends DAO<Notification, Long> {
 
     Notification find(Long key);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/PlainAttrDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/PlainAttrDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/PlainAttrDAO.java
new file mode 100644
index 0000000..8b21ac2
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/PlainAttrDAO.java
@@ -0,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.persistence.api.dao;
+
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+
+public interface PlainAttrDAO extends DAO<PlainAttr, Long> {
+
+    <T extends PlainAttr> T find(Long key, Class<T> reference);
+
+    <T extends PlainAttr> void delete(Long key, Class<T> reference);
+
+    <T extends PlainAttr> void delete(T attr);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/PlainAttrValueDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/PlainAttrValueDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/PlainAttrValueDAO.java
new file mode 100644
index 0000000..e6d9226
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/PlainAttrValueDAO.java
@@ -0,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.persistence.api.dao;
+
+import java.util.List;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+
+public interface PlainAttrValueDAO extends DAO<PlainAttrValue, Long> {
+
+    <T extends PlainAttrValue> T find(Long key, Class<T> reference);
+
+    <T extends PlainAttrValue> List<T> findAll(Class<T> reference);
+
+    <T extends PlainAttrValue> T save(T attributeValue) throws InvalidEntityException;
+
+    <T extends PlainAttrValue> void delete(Long key, Class<T> reference);
+
+    <T extends PlainAttrValue> void delete(T attributeValue);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/PlainSchemaDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/PlainSchemaDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/PlainSchemaDAO.java
new file mode 100644
index 0000000..ea9860e
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/PlainSchemaDAO.java
@@ -0,0 +1,38 @@
+/*
+ * 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.persistence.api.dao;
+
+import java.util.List;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.entity.AttributableUtil;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+
+public interface PlainSchemaDAO extends DAO<PlainSchema, String> {
+
+    <T extends PlainSchema> T find(String key, Class<T> reference);
+
+    <T extends PlainSchema> List<T> findAll(Class<T> reference);
+
+    <T extends PlainAttr> List<T> findAttrs(PlainSchema schema, Class<T> reference);
+
+    <T extends PlainSchema> T save(T schema) throws InvalidEntityException;
+
+    void delete(String name, AttributableUtil attributableUtil);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/PolicyDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/PolicyDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/PolicyDAO.java
index 27f4edf..0161c23 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/PolicyDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/PolicyDAO.java
@@ -26,7 +26,7 @@ import org.apache.syncope.persistence.api.entity.PasswordPolicy;
 import org.apache.syncope.persistence.api.entity.Policy;
 import org.apache.syncope.persistence.api.entity.SyncPolicy;
 
-public interface PolicyDAO extends DAO<Policy> {
+public interface PolicyDAO extends DAO<Policy, Long> {
 
     <T extends Policy> T find(Long key);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ReportDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ReportDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ReportDAO.java
index eef08f7..d154534 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ReportDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ReportDAO.java
@@ -20,10 +20,10 @@ package org.apache.syncope.persistence.api.dao;
 
 import java.util.List;
 import org.apache.syncope.persistence.api.dao.search.OrderByClause;
-import org.apache.syncope.persistence.api.dao.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
 import org.apache.syncope.persistence.api.entity.Report;
 
-public interface ReportDAO extends DAO<Report> {
+public interface ReportDAO extends DAO<Report, Long> {
 
     Report find(Long key);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ReportExecDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ReportExecDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ReportExecDAO.java
index 1cad2c3..dc1c2bf 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ReportExecDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/ReportExecDAO.java
@@ -19,11 +19,11 @@
 package org.apache.syncope.persistence.api.dao;
 
 import java.util.List;
-import org.apache.syncope.persistence.api.dao.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
 import org.apache.syncope.persistence.api.entity.Report;
 import org.apache.syncope.persistence.api.entity.ReportExec;
 
-public interface ReportExecDAO extends DAO<ReportExec> {
+public interface ReportExecDAO extends DAO<ReportExec, Long> {
 
     ReportExec find(Long key);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/RoleDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/RoleDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/RoleDAO.java
index a45b676..b2d7dd3 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/RoleDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/RoleDAO.java
@@ -21,18 +21,18 @@ package org.apache.syncope.persistence.api.dao;
 import java.util.List;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.persistence.api.dao.search.OrderByClause;
-import org.apache.syncope.persistence.api.dao.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
 import org.apache.syncope.persistence.api.entity.Entitlement;
 import org.apache.syncope.persistence.api.entity.ExternalResource;
 import org.apache.syncope.persistence.api.entity.Policy;
 import org.apache.syncope.persistence.api.entity.membership.Membership;
 import org.apache.syncope.persistence.api.entity.role.RDerAttr;
-import org.apache.syncope.persistence.api.entity.role.RNormAttr;
-import org.apache.syncope.persistence.api.entity.role.RNormAttrValue;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttr;
+import org.apache.syncope.persistence.api.entity.role.RPlainAttrValue;
 import org.apache.syncope.persistence.api.entity.role.RVirAttr;
 import org.apache.syncope.persistence.api.entity.role.Role;
 
-public interface RoleDAO extends SubjectDAO<RNormAttr, RDerAttr, RVirAttr> {
+public interface RoleDAO extends SubjectDAO<RPlainAttr, RDerAttr, RVirAttr> {
 
     Role find(Long key);
 
@@ -58,9 +58,9 @@ public interface RoleDAO extends SubjectDAO<RNormAttr, RDerAttr, RVirAttr> {
 
     List<Role> findByDerAttrValue(String schemaName, String value);
 
-    List<Role> findByAttrValue(String schemaName, RNormAttrValue attrValue);
+    List<Role> findByAttrValue(String schemaName, RPlainAttrValue attrValue);
 
-    Role findByAttrUniqueValue(String schemaName, RNormAttrValue attrUniqueValue);
+    Role findByAttrUniqueValue(String schemaName, RPlainAttrValue attrUniqueValue);
 
     List<Role> findByResource(ExternalResource resource);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/SecurityQuestionDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/SecurityQuestionDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/SecurityQuestionDAO.java
index a1ce799..efe1aa7 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/SecurityQuestionDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/SecurityQuestionDAO.java
@@ -19,10 +19,10 @@
 package org.apache.syncope.persistence.api.dao;
 
 import java.util.List;
-import org.apache.syncope.persistence.api.dao.validation.InvalidEntityException;
+import org.apache.syncope.persistence.api.attrvalue.validation.InvalidEntityException;
 import org.apache.syncope.persistence.api.entity.user.SecurityQuestion;
 
-public interface SecurityQuestionDAO extends DAO<SecurityQuestion> {
+public interface SecurityQuestionDAO extends DAO<SecurityQuestion, Long> {
 
     SecurityQuestion find(Long key);
 


[11/32] syncope git commit: Upgrading Spring

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


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

Branch: refs/heads/2_0_X
Commit: 257be980a6466079640be4a676b66342e3b55373
Parents: f3a0871 4b71b2c
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu Jan 1 12:35:11 2015 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Jan 1 12:35:11 2015 +0100

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


http://git-wip-us.apache.org/repos/asf/syncope/blob/257be980/pom.xml
----------------------------------------------------------------------
diff --cc pom.xml
index ca77f16,e4565ec..7c18e54
--- a/pom.xml
+++ b/pom.xml
@@@ -320,24 -315,24 +320,24 @@@ under the License
  
      <commons-jexl.version>2.1.1</commons-jexl.version>
      <commons-lang.version>3.3.2</commons-lang.version>
 -        
 -    <hc.client.version>4.2.6</hc.client.version>
 +    <commons-codec.version>1.10</commons-codec.version>
 +
 +    <activiti.version>5.16.4</activiti.version>
  
 -    <activiti.version>5.15.1</activiti.version>
 +    <aspectj.version>1.8.4</aspectj.version>
  
 -    <cxf.version>2.7.14</cxf.version>	
 -    <spring.version>3.2.13.RELEASE</spring.version>
 -    <spring-security.version>3.1.7.RELEASE</spring-security.version>
 -    <aspectj.version>1.7.4</aspectj.version>
 -    <jackson.version>1.9.13</jackson.version>
 -    <xstream.version>1.4.7</xstream.version>
 +    <cxf.version>3.0.3</cxf.version>	
-     <spring.version>4.0.8.RELEASE</spring.version>
++    <spring.version>4.0.9.RELEASE</spring.version>
 +    <spring-security.version>3.2.5.RELEASE</spring-security.version>
 +    <jackson.version>2.4.4</jackson.version>
      <velocity.version>1.7</velocity.version>
      <velocitytools.version>2.0</velocitytools.version>
 -    <quartz.version>2.1.7</quartz.version>
 +    <quartz.version>2.2.1</quartz.version>
  
 -    <openjpa.version>2.2.2</openjpa.version>
 -    <bval.version>0.5</bval.version>
 +    <openjpa.version>2.3.0</openjpa.version>
 +    <hibernate-validator.version>5.1.3.Final</hibernate-validator.version>
      <commons-dbcp.version>1.4</commons-dbcp.version>
 +    <commons.logging.version>1.1.3</commons.logging.version>
  
      <cocoon.version>3.0.0-alpha-3</cocoon.version>
  


[17/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/test/resources/content.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/test/resources/content.xml b/syncope620/server/persistence-jpa/src/test/resources/content.xml
new file mode 100644
index 0000000..80e1d19
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/test/resources/content.xml
@@ -0,0 +1,1125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<dataset>
+  <SyncopeConf id="1" 
+               creator="admin" lastModifier="admin"
+               creationDate="2014-06-20 11:00:00" lastChangeDate="2014-06-20 11:00:00"/>
+
+  <CPlainSchema name="password.cipher.algorithm" type="String"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="1" owner_id="1" schema_name="password.cipher.algorithm"/>
+  <CPlainAttrValue id="1" attribute_id="1" stringValue="SHA1"/>
+
+  <!-- notificationjob.cronExpression:
+  + not existing: NotificationJob runs according to Notification.DEFAULT_CRON_EXP
+  + provided as empty string: NotificationJob disabled
+  + provided as non-empty string: NotificationJob runs according to the given value -->
+  <CPlainSchema name="notificationjob.cronExpression" type="String"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+
+  <CPlainSchema name="notification.maxRetries" type="Long"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="3" owner_id="1" schema_name="notification.maxRetries"/>
+  <CPlainAttrValue id="3" attribute_id="3" longValue="3"/>
+
+  <CPlainSchema name="token.length" type="Long"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="4" owner_id="1" schema_name="token.length"/>
+  <CPlainAttrValue id="4" attribute_id="4" longValue="256"/>
+
+  <CPlainSchema name="token.expireTime" type="Long"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="5" owner_id="1" schema_name="token.expireTime"/>
+  <CPlainAttrValue id="5" attribute_id="5" longValue="60"/>
+
+  <CPlainSchema name="selfRegistration.allowed" type="Boolean"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="6" owner_id="1" schema_name="selfRegistration.allowed"/>
+  <CPlainAttrValue id="6" attribute_id="6" booleanValue="1"/>
+
+  <CPlainSchema name="passwordReset.allowed" type="Boolean"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="7" owner_id="1" schema_name="passwordReset.allowed"/>
+  <CPlainAttrValue id="7" attribute_id="7" booleanValue="1"/>
+
+  <CPlainSchema name="passwordReset.securityQuestion" type="Boolean"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="8" owner_id="1" schema_name="passwordReset.securityQuestion"/>
+  <CPlainAttrValue id="8" attribute_id="8" booleanValue="1"/>
+
+  <CPlainSchema name="authentication.statuses" type="String"
+                mandatoryCondition="true" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="9" owner_id="1" schema_name="authentication.statuses"/>
+  <CPlainAttrValue id="9" attribute_id="9" stringValue="created"/>
+  <CPlainAttrValue id="10" attribute_id="9" stringValue="active"/>
+
+  <!-- Save user login date upon successful authentication -->
+  <CPlainSchema name="log.lastlogindate" type="Boolean"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="11" owner_id="1" schema_name="log.lastlogindate"/>
+  <CPlainAttrValue id="11" attribute_id="11" booleanValue="1"/>
+
+  <!-- For usage with admin console -->
+  <CPlainSchema name="admin.user.layout" type="String"
+                mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CPlainSchema name="self.user.layout" type="String"
+                mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CPlainSchema name="admin.role.layout" type="String"
+                mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CPlainSchema name="self.role.layout" type="String"
+                mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CPlainSchema name="admin.membership.layout" type="String"
+                mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  <CPlainSchema name="self.membership.layout" type="String"
+                mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+  
+  <!-- sample policies -->
+  <Policy DTYPE="SyncPolicy" id="1" description="global sync policy" type="GLOBAL_SYNC" 
+          specification='{"userJavaRule":null,"roleJavaRule":null,"conflictResolutionAction":"IGNORE","userAltSearchSchemas":[],"roleAltSearchSchemas":[]}'/>
+  <Policy DTYPE="PasswordPolicy" id="2" description="global password policy" type="GLOBAL_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='{"userJavaRule":null,"roleJavaRule":null,"conflictResolutionAction":"ALL","userAltSearchSchemas":["username","firstname"],"roleAltSearchSchemas":[]}'/>
+  <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":false}'/>
+  <Policy DTYPE="AccountPolicy" id="5" description="global account policy" type="GLOBAL_ACCOUNT" 
+          specification='{"maxLength":0,"minLength":0,"pattern":null,"allUpperCase":false,"allLowerCase":false,"propagateSuspension":false,"permittedLoginRetries":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,"permittedLoginRetries":3,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[]}'/>
+  <Policy DTYPE="SyncPolicy" id="7" description="sync policy 1" type="SYNC" 
+          specification='{"userJavaRule":null,"roleJavaRule":null,"conflictResolutionAction":"IGNORE","userAltSearchSchemas":[],"roleAltSearchSchemas":[]}'/>
+  <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='{"userJavaRule":null,"roleJavaRule":null,"conflictResolutionAction":"IGNORE","userAltSearchSchemas":[],"roleAltSearchSchemas":[]}'/>
+    
+  <SyncopeUser id="1" workflowId="4" status="active" password="5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8" cipherAlgorithm="SHA1"
+               username="rossini" creator="admin" lastModifier="admin"
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00" suspended="0"/>
+  <SyncopeUser id="2" workflowId="6" status="active" password="5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8" cipherAlgorithm="SHA1"
+               username="verdi" creator="admin" lastModifier="admin"
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00" suspended="0"/>
+  <SyncopeUser id="3" workflowId="8" status="active" password="5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8" cipherAlgorithm="SHA1"
+               username="vivaldi" creator="admin" lastModifier="admin"
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00" suspended="0"/>
+  <SyncopeUser id="4" workflowId="10" status="active" password="5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8" cipherAlgorithm="SHA1"
+               username="bellini" creator="admin" lastModifier="admin"
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00" suspended="0"/>
+  <SyncopeUser id="5" workflowId="12" status="active" password="5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8" cipherAlgorithm="SHA1"
+               username="puccini" creator="admin" lastModifier="admin" 
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00" suspended="0"/>
+
+  <SyncopeRole id="1" name="root"
+               creator="admin" lastModifier="admin" 
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeRole id="2" name="child" parent_id="1"
+               creator="admin" lastModifier="admin" 
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeRole id="3" name="citizen"
+               creator="admin" lastModifier="admin" 
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeRole id="4" name="employee" parent_id="3"
+               creator="admin" lastModifier="admin" 
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeRole id="5" name="secretary" parent_id="4"
+               creator="admin" lastModifier="admin" 
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeRole id="6"
+               name="director" parent_id="4" userOwner_id="5"
+               inheritAttrs="1" inheritDerAttrs="1" inheritVirAttrs="1"
+               inheritPasswordPolicy="0" inheritAccountPolicy="0"
+               passwordPolicy_id="4"
+               accountPolicy_id="6"
+               creator="admin" lastModifier="admin" 
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeRole id="7"
+               name="managingDirector" parent_id="6"
+               inheritAttrs="1" inheritDerAttrs="1" inheritVirAttrs="1"
+               inheritPasswordPolicy="1" inheritAccountPolicy="1" inheritOwner="1"
+               creator="admin" lastModifier="admin" 
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeRole id="8"
+               name="otherchild" parent_id="1"
+               inheritVirAttrs="1"
+               passwordPolicy_id="4"
+               creator="admin" lastModifier="admin" 
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeRole id="9" name="roleForWorkflowApproval" parent_id="1"
+               creator="admin" lastModifier="admin" 
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeRole id="10"
+               name="managingConsultant" parent_id="6"
+               inheritAttrs="1" inheritDerAttrs="1" inheritVirAttrs="1"
+               inheritPasswordPolicy="1" inheritAccountPolicy="1" inheritOwner="0"
+               creator="admin" lastModifier="admin" 
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeRole id="11" name="roleForWorkflowOptIn" parent_id="1"
+               creator="admin" lastModifier="admin" 
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeRole id="12" name="aRoleForPropagation" parent_id="1"
+               creator="admin" lastModifier="admin" 
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeRole id="13" name="bRoleForPropagation" parent_id="1"
+               creator="admin" lastModifier="admin" 
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeRole id="14"
+               name="artDirector" parent_id="4"
+               inheritAttrs="1" inheritDerAttrs="1" inheritVirAttrs="1"
+               inheritPasswordPolicy="0" inheritAccountPolicy="0"
+               passwordPolicy_id="8"
+               accountPolicy_id="6"
+               creator="admin" lastModifier="admin" 
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+
+  <Membership id="1" user_id="1" role_id="1"
+              creator="admin" lastModifier="admin" 
+              creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <Membership id="2" user_id="2" role_id="1"
+              creator="admin" lastModifier="admin" 
+              creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <Membership id="3" user_id="2" role_id="2"
+              creator="admin" lastModifier="admin" 
+              creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <Membership id="4" user_id="4" role_id="7"
+              creator="admin" lastModifier="admin" 
+              creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <Membership id="5" user_id="1" role_id="8"
+              creator="admin" lastModifier="admin" 
+              creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <Membership id="6" user_id="2" role_id="3"
+              creator="admin" lastModifier="admin" 
+              creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <Membership id="7" user_id="5" role_id="14"
+              creator="admin" lastModifier="admin" 
+              creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+
+  <UPlainSchema name="fullname" type="String"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="1" readonly="0"/>
+  <UPlainSchema name="userId" type="String"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="1" readonly="0"
+                validatorClass="org.apache.syncope.persistence.jpa.attrvalue.validation.EmailAddressValidator"/>
+  <UPlainSchema name="loginDate" type="Date"
+                mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"
+                conversionPattern="yyyy-MM-dd"/>
+  <UPlainSchema name="firstname" type="String"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <UPlainSchema name="surname" type="String"
+                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <UPlainSchema name="type" type="String"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <UPlainSchema name="email" type="String"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
+                validatorClass="org.apache.syncope.persistence.jpa.attrvalue.validation.EmailAddressValidator"/>
+  <UPlainSchema name="activationDate" type="Date"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
+                conversionPattern="yyyy-MM-dd'T'HH:mm:ss.SSSZ"/>
+  <UPlainSchema name="uselessReadonly" type="String"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="1"/>
+  <UPlainSchema name="cool" type="Boolean"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <UPlainSchema name="gender" type="Enum"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
+                enumerationValues="M;F"/>
+  <UPlainSchema name="aLong" type="Long"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <UPlainSchema name="makeItDouble" type="Long"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <UPlainSchema name="obscure" type="Encrypted"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
+                secretKey="7abcdefghilmnopqrstuvz9#" cipherAlgorithm="SHA"/>
+  <UPlainSchema name="photo" type="Binary"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
+                mimeType="image/jpeg"/>
+
+  <UDerSchema name="csvuserid" expression="firstname + ',' + surname"/>
+  <UDerSchema name="cn" expression="surname + ', ' + firstname"/>
+  <UDerSchema name="noschema" expression="surname + ', ' + notfound"/>
+
+  <UVirSchema name="virtualdata"/>
+
+  <RPlainSchema name="icon" type="String"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>                
+  <RPlainSchema name="show" type="Boolean"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <RPlainSchema name="rderived_sx" type="String"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <RPlainSchema name="rderived_dx" type="String"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>           
+  <RPlainSchema name="title" type="String"
+                mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+
+  <RDerSchema name="rderiveddata" expression="rderived_sx + '-' + rderived_dx"/>
+  <RDerSchema name="displayProperty" expression="icon + ': ' + show"/>
+  <RDerSchema name="rderToBePropagated" expression="rderived_sx + '-' + rderived_dx"/>
+
+  <RVirSchema name="rvirtualdata"/>
+
+  <!-- rderiveddata is used to verify der schema deletion -->
+  <RDerSchema name="rderivedschema" expression="rderived_sx + '-' + rderived_dx"/>
+
+  <MPlainSchema name="subscriptionDate" type="Date"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
+                conversionPattern="yyyy-MM-dd'T'HH:mm:ss.SSSZ"/>
+  <MPlainSchema name="mderived_sx" type="String"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <MPlainSchema name="mderived_dx" type="String"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>          
+  <MPlainSchema name="postalAddress" type="String"
+                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+
+  <MDerSchema name="mderiveddata" expression="mderived_sx + '-' + mderived_dx"/>
+  <MDerSchema name="mderToBePropagated" expression="mderived_sx + '-' + mderived_dx"/>
+
+  <MVirSchema name="mvirtualdata"/>
+  
+  <UPlainAttr id="99" owner_id="1" schema_name="type"/>
+  <UPlainAttrValue id="9" attribute_id="99" stringValue="G"/>
+  <UPlainAttr id="100" owner_id="1" schema_name="fullname"/>
+  <UPlainAttrUniqueValue id="10" attribute_id="100" schema_name="fullname" stringValue="Gioacchino Rossini"/>
+  <UPlainAttr id="101" owner_id="1" schema_name="firstname"/>
+  <UPlainAttrValue id="11" attribute_id="101" stringValue="Gioacchino"/>
+  <UPlainAttr id="102" owner_id="1" schema_name="surname"/>
+  <UPlainAttrValue id="12" attribute_id="102" stringValue="Rossini"/>
+  <UPlainAttr id="103" owner_id="1" schema_name="userId"/>
+  <UPlainAttrUniqueValue id="13" attribute_id="103" schema_name="userId" stringValue="rossini@apache.org"/>
+  <UPlainAttr id="104" owner_id="1" schema_name="loginDate"/>
+  <UPlainAttrValue id="14" attribute_id="104" dateValue="2009-05-26"/>
+  <UPlainAttrValue id="15" attribute_id="104" dateValue="2010-05-26 15:40:04"/>
+
+  <UPlainAttr id="105" owner_id="2" schema_name="fullname"/>
+  <UPlainAttrUniqueValue id="16" attribute_id="105" schema_name="fullname" stringValue="Giuseppe Verdi"/>
+  <UPlainAttr id="106" owner_id="2" schema_name="firstname"/>
+  <UPlainAttrValue id="17" attribute_id="106" stringValue="Giuseppe"/>
+  <UPlainAttr id="107" owner_id="2" schema_name="surname"/>
+  <UPlainAttrValue id="18" attribute_id="107" stringValue="Verdi"/>
+  <UPlainAttr id="108" owner_id="2" schema_name="userId"/>
+  <UPlainAttrUniqueValue id="19" attribute_id="108" schema_name="userId" stringValue="verdi@apache.org"/>
+
+  <UPlainAttr id="109" owner_id="3" schema_name="firstname"/>
+  <UPlainAttrValue id="20" attribute_id="109" stringValue="Antonio"/>
+  <UPlainAttr id="110" owner_id="3" schema_name="surname"/>
+  <UPlainAttrValue id="21" attribute_id="110" stringValue="Vivaldi"/>
+  <UPlainAttr id="111" owner_id="3" schema_name="fullname"/>
+  <UPlainAttrUniqueValue id="22" attribute_id="111" schema_name="fullname" stringValue="Antonio Vivaldi"/>
+  <UPlainAttr id="112" owner_id="3" schema_name="userId"/>
+  <UPlainAttrUniqueValue id="23" attribute_id="112" schema_name="userId" stringValue="vivaldi@apache.org"/>
+
+  <UPlainAttr id="113" owner_id="4" schema_name="firstname"/>
+  <UPlainAttrValue id="24" attribute_id="113" stringValue="Vincenzo"/>
+  <UPlainAttr id="114" owner_id="4" schema_name="surname"/>
+  <UPlainAttrValue id="25" attribute_id="114" stringValue="Bellini"/>
+  <UPlainAttr id="115" owner_id="4" schema_name="fullname"/>
+  <UPlainAttrUniqueValue id="26" attribute_id="115" schema_name="fullname" stringValue="Vincenzo Bellini"/>
+  <UPlainAttr id="116" owner_id="4" schema_name="userId"/>
+  <UPlainAttrUniqueValue id="27" attribute_id="116" schema_name="userId" stringValue="bellini@apache.org"/>
+  <UPlainAttr id="117" owner_id="4" schema_name="loginDate"/>
+  <UPlainAttrValue id="28" attribute_id="117" dateValue="2009-06-24"/>
+  <UPlainAttr id="118" owner_id="4" schema_name="cool"/>
+  <UPlainAttrValue id="29" attribute_id="118" booleanValue="1"/>
+  <UPlainAttr id="119" owner_id="4" schema_name="gender"/>
+  <UPlainAttrValue id="30" attribute_id="119" stringValue="M"/>
+  
+  <UPlainAttr id="120" owner_id="5" schema_name="firstname"/>
+  <UPlainAttrValue id="31" attribute_id="120" stringValue="Giacomo"/>
+  <UPlainAttr id="121" owner_id="5" schema_name="surname"/>
+  <UPlainAttrValue id="32" attribute_id="121" stringValue="Puccini"/>
+  <UPlainAttr id="122" owner_id="5" schema_name="fullname"/>
+  <UPlainAttrUniqueValue id="33" attribute_id="122" schema_name="fullname" stringValue="Giacomo Puccini"/>
+  <UPlainAttr id="123" owner_id="5" schema_name="userId"/>
+  <UPlainAttrUniqueValue id="34" attribute_id="123" schema_name="userId" stringValue="puccini@apache.org"/>
+  
+  <UPlainAttr id="124" owner_id="2" schema_name="email"/>
+  <UPlainAttrValue id="35" attribute_id="124" stringValue="verdi@syncope.org"/>
+  <UPlainAttr id="125" owner_id="3" schema_name="email"/>
+  <UPlainAttrValue id="36" attribute_id="125" stringValue="vivaldi@syncope.org"/>
+  <UPlainAttr id="126" owner_id="3" schema_name="type"/>
+  <UPlainAttrValue id="37" attribute_id="126" stringValue="F"/>
+    
+  <UVirAttr id="1000" virSchema_name="virtualdata" owner_id="3"/>
+
+  <UVirSchema name="virtualReadOnly" READONLY="1"/>
+  
+  <UDerAttr id="100" derSchema_name="cn" owner_id="3"/>
+  <UDerAttr id="101" derSchema_name="cn" owner_id="1"/>
+
+  <RPlainAttrTemplate id="600" owner_id="1" schema_name="icon"/>
+  <RPlainAttr id="600" owner_id="1" template_id="600"/>
+  <RPlainAttrValue attribute_id="600" id="40" stringValue="niceIcon"/>
+
+  <RPlainAttrTemplate id="700" owner_id="2" schema_name="icon"/>
+  <RPlainAttr id="700" owner_id="2" template_id="700"/>
+  <RPlainAttrValue attribute_id="700" id="41" stringValue="badIcon"/>
+
+  <RPlainAttrTemplate id="800" owner_id="1" schema_name="show"/>
+  <RPlainAttr id="800" owner_id="1" template_id="800"/>
+  <RPlainAttrValue attribute_id="800" id="42" booleanValue="1"/>
+
+  <RPlainAttrTemplate id="900" owner_id="6" schema_name="icon"/>
+  <RPlainAttr id="900" owner_id="6" template_id="900"/>
+  <RPlainAttrValue attribute_id="900" id="43" stringValue="icon6"/>
+
+  <RPlainAttrTemplate id="950" owner_id="4" schema_name="icon"/>
+  <RPlainAttr id="950" owner_id="4" template_id="950"/>
+  <RPlainAttrValue attribute_id="950" id="44" stringValue="icon4"/>
+
+  <RPlainAttrTemplate id="992" owner_id="1" schema_name="rderived_sx"/>
+  <RPlainAttr id="992" owner_id="1" template_id="992"/>
+  <RPlainAttrValue attribute_id="992" id="92" stringValue="sx"/>
+
+  <RPlainAttrTemplate id="993" owner_id="1" schema_name="rderived_dx"/>
+  <RPlainAttr id="993" owner_id="1" template_id="993"/>
+  <RPlainAttrValue attribute_id="993" id="93" stringValue="dx"/>
+
+  <RPlainAttrTemplate id="994" owner_id="12" schema_name="title"/>
+  <RPlainAttr id="994" owner_id="12" template_id="994"/>
+  <RPlainAttrValue attribute_id="994" id="94" stringValue="r12"/>
+  
+  <RPlainAttrTemplate id="995" owner_id="13" schema_name="title"/>
+  <RPlainAttr id="995" owner_id="13" template_id="995"/>
+  <RPlainAttrValue attribute_id="995" id="95" stringValue="r13"/>
+
+  <RDerAttrTemplate id="1000" owner_id="1" schema_name="rderiveddata"/>
+  <RDerAttr id="1000" owner_id="1" template_id="1000"/>
+    
+  <RDerAttrTemplate id="1001" owner_id="1" schema_name="displayProperty"/>
+  <RDerAttr id="1001" owner_id="1" template_id="1001"/>
+  
+  <RDerAttrTemplate id="1002" owner_id="4" schema_name="displayProperty"/>
+  <RDerAttr id="1002" owner_id="4" template_id="1002"/>
+
+  <RDerAttrTemplate id="1003" owner_id="1" schema_name="rderToBePropagated"/>    
+  <RDerAttr id="1003" owner_id="1" template_id="1003"/>    
+
+  <RVirAttrTemplate id="100" owner_id="4" schema_name="rvirtualdata"/>
+  <RVirAttr id="100" owner_id="4" template_id="100"/>
+
+  <RVirAttrTemplate id="101" owner_id="3" schema_name="rvirtualdata"/>
+
+  <MPlainAttrTemplate id="98" owner_id="1" schema_name="mderived_sx"/>
+  
+  <MPlainAttrTemplate id="99" owner_id="1" schema_name="mderived_dx"/>
+
+  <MPlainAttrTemplate id="100" owner_id="7" schema_name="subscriptionDate"/>
+  <MPlainAttr id="100" owner_id="4" template_id="100"/>
+  <MPlainAttrValue attribute_id="100" id="90" dateValue="2009-05-26"/>
+  <MPlainAttrValue attribute_id="100" id="91" dateValue="2010-05-26 15:40:04"/>
+
+  <MPlainAttrTemplate id="101" owner_id="8" schema_name="subscriptionDate"/>
+
+  <MPlainAttrTemplate id="102" owner_id="1" schema_name="mderived_sx"/>
+  <MPlainAttr id="102" owner_id="1" template_id="102"/>
+  <MPlainAttrValue attribute_id="102" id="92" stringValue="sx"/>
+
+  <MPlainAttrTemplate id="103" owner_id="1" schema_name="mderived_dx"/>
+  <MPlainAttr id="103" owner_id="1" template_id="103"/>
+  <MPlainAttrValue attribute_id="103" id="93" stringValue="dx"/>
+
+  <MPlainAttrTemplate id="104" owner_id="12" schema_name="postalAddress"/>
+
+  <MDerAttrTemplate id="99" owner_id="1" schema_name="mderiveddata"/>
+  <MDerAttr id="99" owner_id="1" template_id="99"/>
+  
+  <MDerAttrTemplate id="100" owner_id="1" schema_name="mderToBePropagated"/>  
+    
+  <MVirAttrTemplate id="100" owner_id="2" schema_name="mvirtualdata"/>
+
+  <ConnInstance id="100" displayName="ConnInstance100"
+                location="${connid.location}"
+                bundleName="net.tirasa.connid.bundles.soap"
+                connectorName="net.tirasa.connid.bundles.soap.WebServiceConnector"
+                version="${connid.soap.version}"
+                jsonConf='[{"schema":{"name":"endpoint","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["http://localhost:9080/wssample/services/provisioning"]},{"schema":{"name":"servicename","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["net.tirasa.connid.bundles.soap.provisioning.interfaces.Provisioning"]}]'/>
+  <ConnInstance_capabilities ConnInstance_id="100" capabilities="ONE_PHASE_CREATE"/>
+  <ConnInstance_capabilities ConnInstance_id="100" capabilities="ONE_PHASE_UPDATE"/>
+  <ConnInstance_capabilities ConnInstance_id="100" capabilities="ONE_PHASE_DELETE"/>
+  <ConnInstance_capabilities ConnInstance_id="100" capabilities="TWO_PHASES_CREATE"/>
+  <ConnInstance_capabilities ConnInstance_id="100" capabilities="TWO_PHASES_UPDATE"/>
+  <ConnInstance_capabilities ConnInstance_id="100" capabilities="TWO_PHASES_DELETE"/>
+  <ConnInstance_capabilities ConnInstance_id="100" capabilities="SEARCH"/>
+
+  <ConnInstance id="101" displayName="H2"
+                location="connid://${testconnectorserver.key}@localhost:${testconnectorserver.port}"
+                bundleName="net.tirasa.connid.bundles.db.table"
+                connectorName="net.tirasa.connid.bundles.db.table.DatabaseTableConnector"
+                version="${connid.db.table.version}"
+                jsonConf='[{"schema":{"name":"disabledStatusValue","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"user","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["sa"]},{"schema":{"name":"keyColumn","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["id"]},{"schema":{"name":"retrievePassword","displayName":null,"helpMessage":null,"type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["true"]},{"schema":{"name":"cipherAlgorithm","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValu
 es":null},"overridable":false,"values":["SHA1"]},{"schema":{"name":"enabledStatusValue","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["true"]},{"schema":{"name":"passwordColumn","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["password"]},{"schema":{"name":"jdbcDriver","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["org.h2.Driver"]},{"schema":{"name":"defaultStatusValue","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["true"]},{"schema":{"name":"table","displayName":null,"helpMessage":null,"type":"java.lang.String","required
 ":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["test"]},{"schema":{"name":"password","displayName":null,"helpMessage":null,"type":"org.identityconnectors.common.security.GuardedString","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["sa"]},{"schema":{"name":"statusColumn","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["status"]},{"schema":{"name":"jdbcUrlTemplate","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["${testdb.url}"]}]'/>
+  <ConnInstance_capabilities ConnInstance_id="101" capabilities="AUTHENTICATE"/>
+  <ConnInstance_capabilities ConnInstance_id="101" capabilities="ONE_PHASE_CREATE"/>
+  <ConnInstance_capabilities ConnInstance_id="101" capabilities="ONE_PHASE_UPDATE"/>
+  <ConnInstance_capabilities ConnInstance_id="101" capabilities="ONE_PHASE_DELETE"/>
+  <ConnInstance_capabilities ConnInstance_id="101" capabilities="TWO_PHASES_CREATE"/>
+  <ConnInstance_capabilities ConnInstance_id="101" capabilities="TWO_PHASES_UPDATE"/>
+  <ConnInstance_capabilities ConnInstance_id="101" capabilities="TWO_PHASES_DELETE"/>
+  <ConnInstance_capabilities ConnInstance_id="101" capabilities="SEARCH"/>
+  <ConnInstance_capabilities ConnInstance_id="101" capabilities="SYNC"/>
+
+  <ConnInstance id="102" displayName="ConnInstance102"
+                location="${connid.location}"
+                bundleName="net.tirasa.connid.bundles.soap"
+                connectorName="net.tirasa.connid.bundles.soap.WebServiceConnector"
+                version="${connid.soap.version}"
+                connRequestTimeout="10"
+                jsonConf='[{"schema":{"name":"servicename","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["net.tirasa.connid.bundles.soap.provisioning.interfaces.Provisioning"]},{"schema":{"name":"endpoint","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":true,"values":["http://localhost:9080/wssample/services/provisioning"]}]'/>
+  <ConnInstance_capabilities ConnInstance_id="102" capabilities="ONE_PHASE_CREATE"/>
+  <ConnInstance_capabilities ConnInstance_id="102" capabilities="ONE_PHASE_UPDATE"/>
+  <ConnInstance_capabilities ConnInstance_id="102" capabilities="ONE_PHASE_DELETE"/>
+  <ConnInstance_capabilities ConnInstance_id="102" capabilities="TWO_PHASES_CREATE"/>
+  <ConnInstance_capabilities ConnInstance_id="102" capabilities="TWO_PHASES_UPDATE"/>
+  <ConnInstance_capabilities ConnInstance_id="102" capabilities="TWO_PHASES_DELETE"/>
+  <ConnInstance_capabilities ConnInstance_id="102" capabilities="SEARCH"/>
+
+  <ConnInstance id="103" displayName="ConnInstance103"
+                location="${connid.location}"
+                bundleName="net.tirasa.connid.bundles.soap"
+                connectorName="net.tirasa.connid.bundles.soap.WebServiceConnector"
+                version="${connid.soap.version}"
+                jsonConf='[{"schema":{"name":"endpoint","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["http://localhost:9080/wssample/services/provisioning"]},{"schema":{"name":"servicename","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["net.tirasa.connid.bundles.soap.provisioning.interfaces.Provisioning"]}]'/>
+
+  <ConnInstance id="104" displayName="CSVDir"
+                location="${connid.location}"
+                bundleName="net.tirasa.connid.bundles.csvdir"
+                connectorName="net.tirasa.connid.bundles.csvdir.CSVDirConnector"
+                version="${connid.csvdir.version}"
+                jsonConf='[{"schema":{"name":"fields","displayName":"fields","helpMessage":"Column names separated by comma","type":"[Ljava.lang.String;","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["id","name","surname","email","password","role","membership","status","deleted"]},{"schema":{"name":"keyColumnNames","displayName":"Key column name","helpMessage":"Name of the column used to identify user uniquely","type":"[Ljava.lang.String;","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["name","surname"]},{"schema":{"name":"deleteColumnName","displayName":"Delete column name","helpMessage":"Name of the column used to specify users to be deleted","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["deleted"]},{"schema":{"name":"passwordColumnName","displayName":"Password column name","helpMessage":"Name of th
 e column used to specify user password","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["password"]},{"schema":{"name":"keyseparator","displayName":"Key separator","helpMessage":"Character used to separate keys in a multi-key scenario","type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[","]},{"schema":{"name":"ignoreHeader","displayName":"Ignore header","helpMessage":"Specify it first line file must be ignored","type":"java.lang.Boolean","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[false]},{"schema":{"name":"fieldDelimiter","displayName":"fieldDelimiter","helpMessage":"fieldDelimiter","type":"char","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[","]},{"schema":{"name":"quotationRequired","displayName":"Value quotation required","
 helpMessage":"Specify if value quotation is required","type":"java.lang.Boolean","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[false]},{"schema":{"name":"statusColumn","displayName":"statusColumn","helpMessage":"Status column","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["status"]},{"schema":{"name":"sourcePath","displayName":"Source path","helpMessage":"Absolute path of a directory where are located CSV files to be processed","type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["${test.csvdir.path}"]},{"schema":{"name":"fileMask","displayName":"File mask","helpMessage":"Regular expression describing files to be processed","type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["test.csv"]}]'/>
+  <ConnInstance_capabilities ConnInstance_id="104" capabilities="ONE_PHASE_CREATE"/>
+  <ConnInstance_capabilities ConnInstance_id="104" capabilities="ONE_PHASE_UPDATE"/>
+  <ConnInstance_capabilities ConnInstance_id="104" capabilities="ONE_PHASE_DELETE"/>
+  <ConnInstance_capabilities ConnInstance_id="104" capabilities="TWO_PHASES_CREATE"/>
+  <ConnInstance_capabilities ConnInstance_id="104" capabilities="TWO_PHASES_UPDATE"/>
+  <ConnInstance_capabilities ConnInstance_id="104" capabilities="TWO_PHASES_DELETE"/>
+  <ConnInstance_capabilities ConnInstance_id="104" capabilities="SEARCH"/>
+  <ConnInstance_capabilities ConnInstance_id="104" capabilities="SYNC"/>
+    
+  <ConnInstance id="105" bundleName="net.tirasa.connid.bundles.ldap" displayName="ApacheDS"
+                location="${connid.location}"
+                connectorName="net.tirasa.connid.bundles.ldap.LdapConnector"
+                version="${connid.ldap.version}" 
+                jsonConf='[{"schema":{"name":"synchronizePasswords","displayName":"Enable Password Synchronization","helpMessage":"If true, the connector will synchronize passwords. The Password Capture Plugin needs to be installed for password synchronization to work.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"maintainLdapGroupMembership","displayName":"Maintain LDAP Group Membership","helpMessage":"When enabled and a user is renamed or deleted, update any LDAP groups to which the user belongs to reflect the new name. Otherwise, the LDAP resource must maintain referential integrity with respect to group membership.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["true"]},{"schema":{"name":"host","displayName":"Host","helpMessage":"The name or IP address of the host where the LDAP server is running.","type":"jav
 a.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["localhost"]},{"schema":{"name":"passwordHashAlgorithm","displayName":"Password Hash Algorithm","helpMessage":"Indicates the algorithm that the Identity system should use to hash the password. Currently supported values are SSHA, SHA, SSHA1, and SHA1. A blank value indicates that the system will not hash passwords. This will cause cleartext passwords to be stored in LDAP unless the LDAP server performs the hash (Netscape Directory Server and iPlanet Directory Server do).","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["SHA"]},{"schema":{"name":"blockSize","displayName":"Block Size","helpMessage":"The maximum number of accounts that can be in a block when retrieving accounts in blocks.","type":"int","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"valu
 es":[]},{"schema":{"name":"useBlocks","displayName":"Use Blocks","helpMessage":"When performing operations on large numbers of accounts, the accounts are processed in blocks to reduce the amount of memory used by the operation. Select this option to process accounts in blocks.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[false]},{"schema":{"name":"usePagedResultControl","displayName":"Use Paged Result Control","helpMessage":"When enabled, the LDAP Paged Results control is preferred over the VLV control when retrieving accounts.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"port","displayName":"TCP Port","helpMessage":"TCP/IP port number used to communicate with the LDAP server.","type":"int","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[1389]},{"schema":{"nam
 e":"vlvSortAttribute","displayName":"VLV Sort Attribute","helpMessage":"Specify the sort attribute to use for VLV indexes on the resource.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"statusManagementClass","displayName":"Status management class ","helpMessage":"Class to be used to manage enabled/disabled status. If no class is specified then identity status management wont be possible.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["net.tirasa.connid.bundles.ldap.commons.AttributeStatusManagement"]},{"schema":{"name":"accountObjectClasses","displayName":"Account Object Classes","helpMessage":"The object class or classes that will be used when creating new user objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to s
 eparate multiple object classes. Some object classes may require that you specify all object classes in the class hierarchy.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["inetOrgPerson"]},{"schema":{"name":"accountUserNameAttributes","displayName":"Account User Name Attributes","helpMessage":"Attribute or attributes which holds the account user name. They will be used when authenticating to find the LDAP entry for the user name to authenticate.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["uid"]},{"schema":{"name":"baseContextsToSynchronize","displayName":"Base Contexts to Synchronize","helpMessage":"One or more starting points in the LDAP tree that will be used to determine if a change should be synchronized. The base contexts attribute will be used to synchronize a change if this property is not set.","type":"[Lja
 va.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["ou=people,o=isp","ou=groups,o=isp"]},{"schema":{"name":"accountSynchronizationFilter","displayName":"LDAP Filter for Accounts to Synchronize","helpMessage":"An optional LDAP filter for the objects to synchronize. Because the change log is for all objects, this filter updates only objects that match the specified filter. If you specify a filter, an object will be synchronized only if it matches the filter and includes a synchronized object class.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"removeLogEntryObjectClassFromFilter","displayName":"Remove Log Entry Object Class from Filter","helpMessage":"If this property is set (the default), the filter used to fetch change log entries does not contain the \"changeLogEntry\" object class, expecting that there are no entri
 es of other object types in the change log.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"passwordDecryptionKey","displayName":"Password Decryption Key","helpMessage":"The key to decrypt passwords with when performing password synchronization.","type":"org.identityconnectors.common.security.GuardedByteArray","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"readSchema","displayName":"Read Schema","helpMessage":"If true, the connector will read the schema from the server. If false, the connector will provide a default schema based on the object classes in the configuration. This property must be true in order to use extended object classes.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"ssl","displayName":"SSL","hel
 pMessage":"Select the check box to connect to the LDAP server using SSL.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"passwordAttributeToSynchronize","displayName":"Password Attribute to Synchronize","helpMessage":"The name of the password attribute to synchronize when performing password synchronization.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"accountSearchFilter","displayName":"LDAP Filter for Retrieving Accounts","helpMessage":"An optional LDAP filter to control which accounts are returned from the LDAP resource. If no filter is specified, only accounts that include all specified object classes are returned.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["uid=*"]},{"schema":{"name":"passwordDec
 ryptionInitializationVector","displayName":"Password Decryption Initialization Vector","helpMessage":"The initialization vector to decrypt passwords with when performing password synchronization.","type":"org.identityconnectors.common.security.GuardedByteArray","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"groupMemberAttribute","displayName":"Group Member Attribute","helpMessage":"The name of the group attribute that will be updated with the distinguished name of the user when the user is added to the group.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"failover","displayName":"Failover Servers","helpMessage":"List all servers that should be used for failover in case the preferred server fails. If the preferred server fails, JNDI will connect to the next available server in the list. List all servers in the
  form of \"ldap://ldap.example.com:389/\", which follows the standard LDAP v3 URLs described in RFC 2255. Only the host and port parts of the URL are relevant in this setting.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"modifiersNamesToFilterOut","displayName":"Filter Out Changes By","helpMessage":"The names (DNs) of directory administrators to filter from the changes. Changes with the attribute \"modifiersName\" that match entries in this list will be filtered out. The standard value is the administrator name used by this adapter, to prevent loops. Entries should be of the format \"cn=Directory Manager\".","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"groupNameAttributes","displayName":"Group Name Attributes","helpMessage":"Attribute or attributes which holds the group nam
 e.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["cn"]},{"schema":{"name":"uidAttribute","displayName":"Uid Attribute","helpMessage":"The name of the LDAP attribute which is mapped to the Uid attribute.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["cn"]},{"schema":{"name":"respectResourcePasswordPolicyChangeAfterReset","displayName":"Respect Resource Password Policy Change-After-Reset","helpMessage":"When this resource is specified in a Login Module (i.e., this resource is a pass-through authentication target) and the resource password policy is configured for change-after-reset, a user whose resource account password has been administratively reset will be required to change that password after successfully authenticating.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overrida
 ble":false,"values":["false"]},{"schema":{"name":"filterWithOrInsteadOfAnd","displayName":"Filter with Or Instead of And","helpMessage":"Normally the the filter used to fetch change log entries is an and-based filter retrieving an interval of change entries. If this property is set, the filter will or together the required change numbers instead.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"principal","displayName":"Principal","helpMessage":"The distinguished name with which to authenticate to the LDAP server.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["uid=admin,ou=system"]},{"schema":{"name":"changeLogBlockSize","displayName":"Change Log Block Size","helpMessage":"The number of change log entries to fetch per query.","type":"int","required":true,"order":0,"confidential":false,"defaultValues":null},
 "overridable":false,"values":[100]},{"schema":{"name":"baseContexts","displayName":"Base Contexts","helpMessage":"One or more starting points in the LDAP tree that will be used when searching the tree. Searches are performed when discovering users from the LDAP server or when looking for the groups of which a user is a member.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["ou=people,o=isp","ou=groups,o=isp"]},{"schema":{"name":"passwordAttribute","displayName":"Password Attribute","helpMessage":"The name of the LDAP attribute which holds the password. When changing an user password, the new password is set to this attribute.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["userpassword"]},{"schema":{"name":"changeNumberAttribute","displayName":"Change Number Attribute","helpMessage":"The name of the change number attribute
  in the change log entry.","type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["changeNumber"]},{"schema":{"name":"objectClassesToSynchronize","displayName":"Object Classes to Synchronize","helpMessage":"The object classes to synchronize. The change log is for all objects; this filters updates to just the listed object classes. You should not list the superclasses of an object class unless you intend to synchronize objects with any of the superclass values. For example, if only \"inetOrgPerson\" objects should be synchronized, but the superclasses of \"inetOrgPerson\" (\"person\", \"organizationalperson\" and \"top\") should be filtered out, then list only \"inetOrgPerson\" here. All objects in LDAP are subclassed from \"top\". For this reason, you should never list \"top\", otherwise no object would be filtered.","type":"[Ljava.lang.String;","required":true,"order":0,"confidential":false,"defaultValues":null},
 "overridable":false,"values":["inetOrgPerson","groupOfUniqueNames"]},{"schema":{"name":"credentials","displayName":"Password","helpMessage":"Password for the principal.","type":"org.identityconnectors.common.security.GuardedString","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["secret"]},{"schema":{"name":"attributesToSynchronize","displayName":"Attributes to Synchronize","helpMessage":"The names of the attributes to synchronize. This ignores updates from the change log if they do not update any of the named attributes. For example, if only \"department\" is listed, then only changes that affect \"department\" will be processed. All other updates are ignored. If blank (the default), then all changes are processed.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"maintainPosixGroupMembership","displayName":"Maintain POSIX Group M
 embership","helpMessage":"When enabled and a user is renamed or deleted, update any POSIX groups to which the user belongs to reflect the new name. Otherwise, the LDAP resource must maintain referential integrity with respect to group membership.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["truemaintainLdapGroupMembership"]}]'/>
+  <ConnInstance_capabilities ConnInstance_id="105" capabilities="ONE_PHASE_CREATE"/>
+  <ConnInstance_capabilities ConnInstance_id="105" capabilities="ONE_PHASE_UPDATE"/>
+  <ConnInstance_capabilities ConnInstance_id="105" capabilities="ONE_PHASE_DELETE"/>
+  <ConnInstance_capabilities ConnInstance_id="105" capabilities="SEARCH"/>
+  
+  <ConnInstance id="106" displayName="H2-test2"
+                location="connid://${testconnectorserver.key}@localhost:${testconnectorserver.port}"
+                bundleName="net.tirasa.connid.bundles.db.table"
+                connectorName="net.tirasa.connid.bundles.db.table.DatabaseTableConnector"
+                version="${connid.db.table.version}"
+                jsonConf='[{"schema":{"name":"disabledStatusValue","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"user","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["sa"]},{"schema":{"name":"keyColumn","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["id"]},{"schema":{"name":"cipherAlgorithm","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["SHA1"]},{"schema":{"name":"enabledStatusValue","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"
 defaultValues":null},"overridable":false,"values":["true"]},{"schema":{"name":"passwordColumn","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["password"]},{"schema":{"name":"jdbcDriver","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["org.h2.Driver"]},{"schema":{"name":"retrievePassword","displayName":null,"helpMessage":null,"type":"java.lang.Boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["true"]},{"schema":{"name":"defaultStatusValue","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["true"]},{"schema":{"name":"password","displayName":null,"helpMessage":null,"type":"org.identityco
 nnectors.common.security.GuardedString","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["sa"]},{"schema":{"name":"statusColumn","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["status"]},{"schema":{"name":"jdbcUrlTemplate","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["${testdb.url}"]},{"schema":{"name":"table","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["test2"]}]'/>
+  <ConnInstance_capabilities ConnInstance_id="106" capabilities="ONE_PHASE_CREATE"/>
+  <ConnInstance_capabilities ConnInstance_id="106" capabilities="ONE_PHASE_UPDATE"/>
+  <ConnInstance_capabilities ConnInstance_id="106" capabilities="SEARCH"/>
+  <ConnInstance_capabilities ConnInstance_id="106" capabilities="SYNC"/>
+  
+  <ConnInstance id="107" bundleName="net.tirasa.connid.bundles.db.table" 
+                location="connid://${testconnectorserver.key}@localhost:${testconnectorserver.port}"
+                connectorName="net.tirasa.connid.bundles.db.table.DatabaseTableConnector" 
+                displayName="H2-testsync" version="${connid.db.table.version}"
+                jsonConf='[{"schema":{"name":"changeLogColumn","displayName":"Change Log Column (Sync)","helpMessage":"=&lt;b&gt;Change Log Column&lt;/b&gt;&lt;br&gt;The change log column store the latest change time. Providing this value the Sync capabilities are activated.","type":"java.lang.String","required":false,"order":21,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"nativeTimestamps","displayName":"Native Timestamps ","helpMessage":"&lt;b&gt;Native Timestamps&lt;/b&gt;&lt;br&gt;Select to retrieve Timestamp data type of the columns in java.sql.Timestamp format from the database table.","type":"boolean","required":false,"order":18,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"cipherAlgorithm","displayName":"Password cipher algorithm (defaults to CLEARTEXT)","helpMessage":"Cipher algorithm used to encode password before to store it onto the database table.\nSpecify one of th
 e values among CLEARTEXT,AES, MD5, SHA1, SHA256 or a custom implementation identified by its class name.","type":"java.lang.String","required":false,"order":24,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"enabledStatusValue","displayName":"Enabled Status Value","helpMessage":"&lt;b&gt;Enabled Status Value&lt;/b&gt;&lt;br&gt;Enter the value for enabled status.","type":"java.lang.String","required":false,"order":12,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"retrievePassword","displayName":"Retrieve password","helpMessage":"Specify if password must be retrieved by default.","type":"boolean","required":true,"order":27,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"datasource","displayName":"Datasource Path","helpMessage":"&lt;b&gt;JDBC Data Source Name/Path&lt;/b&gt;&lt;br&gt;Enter the JDBC Data Source Name/Path to connect to the Or
 acle server. If specified, connector will only try to connect using Datasource and ignore other resource parameters specified.&lt;br&gt;the example value is: &lt;CODE&gt;jdbc/SampleDataSourceName&lt;/CODE&gt;","type":"java.lang.String","required":false,"order":22,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"allNative","displayName":"All native","helpMessage":"&lt;b&gt;All native&lt;/b&gt;&lt;br&gt;Select to retrieve all data type of the columns in a native format from the database table.","type":"boolean","required":false,"order":19,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"user","displayName":"User","helpMessage":"&lt;b&gt;User&lt;/b&gt;&lt;br&gt;Enter the name of the mandatory Database user with permission to account table.","type":"java.lang.String","required":false,"order":4,"confidential":false,"defaultValues":null},"overridable":false,"values":["sa"]},{"schema":{"name"
 :"pwdEncodeToLowerCase","displayName":"Force password encoding to lower case","helpMessage":"Force password encoding to lower case.","type":"boolean","required":false,"order":26,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"jdbcUrlTemplate","displayName":"JDBC Connection URL","helpMessage":"&lt;b&gt;JDBC Connection URL&lt;/b&gt;&lt;br&gt;Specify the JDBC Driver Connection URL.&lt;br&gt; Oracle template is jdbc:oracle:thin:@[host]:[port(1521)]:[DB].&lt;br&gt;  MySQL template is jdbc:mysql://[host]:[port(3306)]/[db], for more info, read the JDBC driver documentation.&lt;br&gt;Could be empty if datasource is provided.","type":"java.lang.String","required":false,"order":15,"confidential":false,"defaultValues":null},"overridable":false,"values":["${testdb.url}"]},{"schema":{"name":"keyColumn","displayName":"Key Column","helpMessage":"&lt;b&gt;Key Column&lt;/b&gt;&lt;br&gt;This mandatory column value will be used as the unique identi
 fier for rows in the table.&lt;br&gt;","type":"java.lang.String","required":true,"order":8,"confidential":false,"defaultValues":null},"overridable":false,"values":["id"]},{"schema":{"name":"validConnectionQuery","displayName":"Validate Connection Query","helpMessage":"&lt;b&gt;Validate Connection Query&lt;/b&gt;&lt;br&gt;There can be specified the check connection alive query. If empty, default implementation will test it using the switch on/off the autocommit. Some select 1 from dummy table could be more efficient.","type":"java.lang.String","required":false,"order":20,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"rethrowAllSQLExceptions","displayName":"Rethrow all SQLExceptions","helpMessage":"If this is not checked, SQL statements which throw SQLExceptions with a 0 ErrorCode will be have the exception caught and suppressed. Check it to have exceptions with 0 ErrorCodes rethrown.","type":"boolean","required":false,"order":17,"confid
 ential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"passwordColumn","displayName":"Password Column","helpMessage":"&lt;b&gt;Password Column&lt;/b&gt;&lt;br&gt;Enter the name of the column in the table that will hold the password values. If empty, no validation on resource and passwords are activated.","type":"java.lang.String","required":false,"order":9,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"jndiProperties","displayName":"Initial JNDI Properties","helpMessage":"&lt;b&gt;Initial JNDI Properties&lt;/b&gt;&lt;br&gt;Could be empty or enter the JDBC JNDI Initial context factory, context provider in a format: key = value.","type":"[Ljava.lang.String;","required":false,"order":23,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"password","displayName":"User Password","helpMessage":"&lt;b&gt;User Password&lt;/b&gt;&lt;br&gt;Enter a user account tha
 t has permission to access accounts table.","type":"org.identityconnectors.common.security.GuardedString","required":false,"order":5,"confidential":true,"defaultValues":null},"overridable":false,"values":["sa"]},{"schema":{"name":"host","displayName":"Host","helpMessage":"&lt;b&gt;Host&lt;/b&gt;&lt;br&gt;Enter the name of the host where the database is running.","type":"java.lang.String","required":false,"order":2,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"port","displayName":"Port","helpMessage":"&lt;b&gt;TCP Port&lt;/b&gt;&lt;br&gt;Enter the port number the database server is listening on.","type":"java.lang.String","required":false,"order":3,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"statusColumn","displayName":"Status Column","helpMessage":"&lt;b&gt;Status Column&lt;/b&gt;&lt;br&gt;Enter the name of the column in the table that will hold the status values. If empty enabled and
  disabled operation wont be performed.","type":"java.lang.String","required":false,"order":10,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"pwdEncodeToUpperCase","displayName":"Force password encoding to upper case","helpMessage":"Force password encoding to upper case.","type":"boolean","required":false,"order":25,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"enableEmptyString","displayName":"Enable writing empty string","helpMessage":"&lt;b&gt;Enable writing empty string&lt;/b&gt;&lt;br&gt;Select to enable support for writing an empty strings, instead of a NULL value, in character based columns defined as not-null in the table schema. This option does not influence the way strings are written for Oracle based tables. By default empty strings are written as a NULL value.","type":"boolean","required":false,"order":16,"confidential":false,"defaultValues":null},"overridable":false,"
 values":["false"]},{"schema":{"name":"database","displayName":"Database","helpMessage":"&lt;b&gt;Database&lt;/b&gt;&lt;br&gt;Enter the name of the database on the database server that contains the table.","type":"java.lang.String","required":false,"order":6,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"defaultStatusValue","displayName":"Default Status Value","helpMessage":"&lt;b&gt;Default Status Value&lt;/b&gt;&lt;br&gt;Enter the value for status in case of status not specified.","type":"java.lang.String","required":false,"order":13,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"table","displayName":"Table","helpMessage":"&lt;b&gt;Table&lt;/b&gt;&lt;br&gt;Enter the name of the table in the database that contains the accounts.","type":"java.lang.String","required":true,"order":7,"confidential":false,"defaultValues":null},"overridable":false,"values":["testsync"]},{"schema":{"name":"disab
 ledStatusValue","displayName":"Disabled Status Value","helpMessage":"&lt;b&gt;Disabled Status Value&lt;/b&gt;&lt;br&gt;Enter the value for disabled status.","type":"java.lang.String","required":false,"order":11,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"jdbcDriver","displayName":"JDBC Driver","helpMessage":"&lt;b&gt;JDBC Driver&lt;/b&gt;&lt;br&gt;Specify the JDBC Driver class name. Oracle is oracle.jdbc.driver.OracleDriver. MySQL is org.gjt.mm.mysql.Driver.&lt;br&gt;Could be empty if datasource is provided.","type":"java.lang.String","required":false,"order":14,"confidential":false,"defaultValues":null},"overridable":false,"values":["org.h2.Driver"]},{"schema":{"name":"quoting","displayName":"Name Quoting","helpMessage":"&lt;b&gt;Name Quoting&lt;/b&gt;&lt;br&gt;Select whether database column names for this resource should be quoted, and the quoting characters. By default, database column names are not quoted (None). For other selec
 tions (Single, Double, Back, or Brackets), column names will appear between single quotes, double quotes, back quotes, or brackets in the SQL generated to access the database.","type":"java.lang.String","required":false,"order":1,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"cipherKey","displayName":"Password cipher key","helpMessage":"Specify key in case of reversible algorithm.","type":"java.lang.String","required":false,"order":25,"confidential":false,"defaultValues":null},"overridable":false,"values":[]}]'/>
+  <ConnInstance_capabilities ConnInstance_id="107" capabilities="ONE_PHASE_CREATE"/>
+  <ConnInstance_capabilities ConnInstance_id="107" capabilities="TWO_PHASES_CREATE"/>
+  <ConnInstance_capabilities ConnInstance_id="107" capabilities="ONE_PHASE_UPDATE"/>
+  <ConnInstance_capabilities ConnInstance_id="107" capabilities="TWO_PHASES_UPDATE"/>
+  <ConnInstance_capabilities ConnInstance_id="107" capabilities="ONE_PHASE_DELETE"/>
+  <ConnInstance_capabilities ConnInstance_id="107" capabilities="TWO_PHASES_DELETE"/>
+  <ConnInstance_capabilities ConnInstance_id="107" capabilities="SEARCH"/>
+  
+  <ExternalResource name="ws-target-resource-1" connector_id="100"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="0" propagationMode="TWO_PHASES"
+                    propagationPriority="0" propagationPrimary="1" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" syncTraceLevel="ALL"
+                    creator="admin" lastModifier="admin" 
+                    creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <ExternalResource name="ws-target-resource-2" connector_id="100"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="1" propagationMode="TWO_PHASES"
+                    propagationPriority="0" propagationPrimary="0" createTraceLevel="FAILURES" deleteTraceLevel="NONE" updateTraceLevel="ALL" syncTraceLevel="ALL"
+                    syncPolicy_id="9"
+                    creator="admin" lastModifier="admin" 
+                    creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <ExternalResource name="ws-target-resource-timeout" connector_id="102"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="1" propagationMode="TWO_PHASES"
+                    propagationPriority="0" propagationPrimary="1" createTraceLevel="FAILURES" deleteTraceLevel="NONE" updateTraceLevel="ALL" syncTraceLevel="ALL"
+                    jsonConf='[{"schema":{"name":"endpoint","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":true,"values":["http://localhost:9080/syncope-build-tools/services/provisioning"]}]'
+                    creator="admin" lastModifier="admin" 
+                    creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <ExternalResource name="ws-target-resource-list-mappings-1" connector_id="100"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="0" propagationMode="TWO_PHASES"
+                    propagationPriority="0" propagationPrimary="0" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" syncTraceLevel="ALL"
+                    creator="admin" lastModifier="admin" 
+                    creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <ExternalResource name="ws-target-resource-list-mappings-2" connector_id="100"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="1" propagationMode="TWO_PHASES"
+                    propagationPriority="0" propagationPrimary="0" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" syncTraceLevel="ALL"
+                    creator="admin" lastModifier="admin" 
+                    creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <ExternalResource name="ws-target-resource-delete" connector_id="102"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="0" propagationMode="TWO_PHASES"
+                    propagationPriority="2" propagationPrimary="0" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" syncTraceLevel="ALL"
+                    creator="admin" lastModifier="admin" 
+                    creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <ExternalResource name="ws-target-resource-update" connector_id="100"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="1" propagationMode="TWO_PHASES"
+                    propagationPriority="0" propagationPrimary="0" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" syncTraceLevel="ALL"
+                    creator="admin" lastModifier="admin" 
+                    creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <ExternalResource name="resource-testdb" connector_id="101"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="1" propagationMode="ONE_PHASE"
+                    propagationPriority="0" propagationPrimary="0" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" syncTraceLevel="ALL"
+                    creator="admin" lastModifier="admin" 
+                    creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <ExternalResource name="resource-testdb2" connector_id="106"
+                    randomPwdIfNotProvided="1" enforceMandatoryCondition="1" propagationMode="ONE_PHASE"
+                    propagationPriority="0" propagationPrimary="0" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" syncTraceLevel="ALL"
+                    creator="admin" lastModifier="admin" 
+                    creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <ExternalResource name="resource-csv" connector_id="104"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="0" propagationMode="ONE_PHASE" syncPolicy_id="3"
+                    propagationPriority="0" propagationPrimary="0" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" syncTraceLevel="ALL"
+                    creator="admin" lastModifier="admin" 
+                    creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <ExternalResource name="ws-target-resource-update-resetsynctoken" connector_id="100" enforceMandatoryCondition="1" propagationMode="TWO_PHASES"
+                    randomPwdIfNotProvided="0" propagationPriority="0" propagationPrimary="0" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" syncTraceLevel="ALL"
+                    userializedSyncToken='{"value":null}'
+                    creator="admin" lastModifier="admin" 
+                    creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <ExternalResource name="resource-ldap" connector_id="105"
+                    randomPwdIfNotProvided="1" enforceMandatoryCondition="1" propagationMode="ONE_PHASE"
+                    propagationPriority="0" propagationPrimary="1"
+                    createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" syncTraceLevel="ALL"
+                    creator="admin" lastModifier="admin" 
+                    creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <ExternalResource_PropActions externalResource_name="resource-ldap"
+                                action="org.apache.syncope.core.propagation.impl.LDAPMembershipPropagationActions"/>
+  <ExternalResource name="ws-target-resource-nopropagation" connector_id="103"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="1" propagationMode="TWO_PHASES"
+                    propagationPriority="0" propagationPrimary="0" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" syncTraceLevel="ALL" 
+                    passwordPolicy_id="4"
+                    creator="admin" lastModifier="admin" 
+                    creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  
+  <!-- The following three resources has been added to verify the issue SYNCOPE-68 -->
+  <ExternalResource name="ws-target-resource-nopropagation2" connector_id="103" enforceMandatoryCondition="1" propagationMode="TWO_PHASES"
+                    randomPwdIfNotProvided="0" propagationPriority="0" propagationPrimary="0" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" syncTraceLevel="ALL"
+                    creator="admin" lastModifier="admin" 
+                    creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <ExternalResource name="ws-target-resource-nopropagation3" connector_id="103" enforceMandatoryCondition="1" propagationMode="TWO_PHASES"
+                    randomPwdIfNotProvided="0" propagationPriority="0" propagationPrimary="0" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" syncTraceLevel="ALL"
+                    creator="admin" lastModifier="admin" 
+                    creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <ExternalResource name="ws-target-resource-nopropagation4" connector_id="103" enforceMandatoryCondition="1" propagationMode="TWO_PHASES"
+                    randomPwdIfNotProvided="0" propagationPriority="0" propagationPrimary="0" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" syncTraceLevel="ALL"
+                    creator="admin" lastModifier="admin" 
+                    creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+                    
+  <!-- External resource for issue SYNCOPE-230 -->
+  <ExternalResource name="resource-db-sync" connector_id="107"
+                    randomPwdIfNotProvided="0" createTraceLevel="ALL" deleteTraceLevel="ALL" syncTraceLevel="ALL" updateTraceLevel="ALL"
+                    enforceMandatoryCondition="0" 
+                    propagationMode="TWO_PHASES" propagationPrimary="0" propagationPriority="0"
+                    creator="admin" lastModifier="admin" 
+                    creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+                    
+  <!-- External resource for issue SYNCOPE-267 -->
+  <ExternalResource name="resource-db-virattr" connector_id="107"
+                    randomPwdIfNotProvided="0" createTraceLevel="ALL" deleteTraceLevel="ALL" syncTraceLevel="ALL" updateTraceLevel="ALL"
+                    enforceMandatoryCondition="0" 
+                    propagationMode="TWO_PHASES" propagationPrimary="0" propagationPriority="0"
+                    creator="admin" lastModifier="admin" 
+                    creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+
+  <!-- Use resource-testdb for passthrough authentication (SYNCOPE-164) in the global account policy -->
+  <Policy_ExternalResource account_policy_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"/>
+  <SyncopeUser_ExternalResource user_id="3" resource_name="ws-target-resource-2"/>
+  <SyncopeUser_ExternalResource user_id="3" resource_name="ws-target-resource-1"/>
+  <SyncopeUser_ExternalResource user_id="5" resource_name="resource-testdb2"/>
+  <SyncopeRole_ExternalResource role_id="3" resource_name="ws-target-resource-list-mappings-1"/>
+  <SyncopeRole_ExternalResource role_id="8" resource_name="ws-target-resource-2"/>
+  <SyncopeRole_ExternalResource role_id="3" resource_name="ws-target-resource-list-mappings-2"/>
+  <SyncopeRole_ExternalResource role_id="7" resource_name="ws-target-resource-nopropagation"/>
+  <SyncopeRole_ExternalResource role_id="10" resource_name="ws-target-resource-nopropagation3"/>
+  <SyncopeRole_ExternalResource role_id="12" resource_name="resource-csv"/>
+  <SyncopeRole_ExternalResource role_id="13" resource_name="resource-csv"/>
+
+  <UMapping id="15" resource_name="ws-target-resource-1"/>
+  <UMappingItem id="99" mapping_id="15" extAttrName="userId"
+                intMappingType="UserId" mandatoryCondition="true"
+                accountid="1" password="0" purpose="PROPAGATION"/>
+  <UMappingItem id="100" extAttrName="email" mapping_id="15"
+                intAttrName="email" intMappingType="UserSchema" mandatoryCondition="true"
+                accountid="0" password="0" purpose="PROPAGATION"/>
+  <UMappingItem id="101" extAttrName="surname" mapping_id="15"
+                intAttrName="surname" intMappingType="UserSchema" mandatoryCondition="true"
+                accountid="0" password="0" purpose="PROPAGATION"/>
+  <UMappingItem id="102" mapping_id="15"
+                extAttrName="__PASSWORD__" intMappingType="Password" mandatoryCondition="true"
+                accountid="0" password="1" purpose="PROPAGATION"/>
+  <UMappingItem id="335" mapping_id="15" 
+                extAttrName="fullname" intAttrName="surname" intMappingType="UserSchema" mandatoryCondition="true"
+                accountid="0" password="0" purpose="PROPAGATION"/>
+  <UMappingItem id="336" mapping_id="15"
+                extAttrName="type" intAttrName="type" intMappingType="UserSchema" mandatoryCondition="true"
+                accountid="0" password="0" purpose="PROPAGATION"/>
+  <UMappingItem id="337" mapping_id="15"
+                extAttrName="name" intAttrName="firstname" intMappingType="UserSchema" mandatoryCondition="false"
+                accountid="0" password="0" purpose="NONE"/>
+  
+  <UMapping id="12" resource_name="ws-target-resource-list-mappings-1"/>
+  <UMappingItem id="103" mapping_id="12"
+                extAttrName="email" intAttrName="email" intMappingType="UserSchema" mandatoryCondition="true"
+                accountid="1" password="0" purpose="PROPAGATION"/>
+  <UMappingItem id="104" extAttrName="surname" mapping_id="12"
+                intAttrName="surname" intMappingType="UserSchema" mandatoryCondition="true"
+                accountid="0" password="0" purpose="PROPAGATION"/>
+
+  <UMapping id="13" resource_name="ws-target-resource-list-mappings-2"/>
+  <UMappingItem id="105" mapping_id="13"
+                extAttrName="userId" intAttrName="userId" intMappingType="UserSchema" mandatoryCondition="true"
+                accountid="1" password="0" purpose="PROPAGATION"/>
+
+  <UMapping id="1" resource_name="ws-target-resource-2"/>
+  <UMappingItem id="106" mapping_id="1" extAttrName="fullname"
+                intAttrName="fullname" intMappingType="UserSchema" mandatoryCondition="true"
+                accountid="1" password="0" purpose="BOTH"/>
+  <UMappingItem id="107" mapping_id="1"
+                extAttrName="__PASSWORD__" intMappingType="Password" mandatoryCondition="true"
+                accountid="0" password="1" purpose="BOTH"/>
+  <UMappingItem id="108" extAttrName="type" mapping_id="1"
+                intAttrName="type" intMappingType="UserSchema" mandatoryCondition="true"
+                accountid="0" password="0" purpose="BOTH"/>
+  <UMappingItem id="109" extAttrName="surname" mapping_id="1"
+                intAttrName="surname" intMappingType="UserSchema" mandatoryCondition="type == 'F'"
+                accountid="0" password="0" purpose="BOTH"/>
+  <UMappingItem id="110" extAttrName="name" mapping_id="1"
+                intAttrName="virtualdata" intMappingType="UserVirtualSchema" mandatoryCondition="type == 'F'"
+                accountid="0" password="0" purpose="BOTH"/>
+  <UMappingItem id="111" extAttrName="fullname" mapping_id="1"
+                intAttrName="cn" intMappingType="UserDerivedSchema" mandatoryCondition="true"
+                accountid="0" password="0" purpose="BOTH"/>
+    
+  <UMapping id="2" resource_name="ws-target-resource-update"/>
+  <UMappingItem id="112" extAttrName="email" mapping_id="2"
+                intAttrName="email" intMappingType="UserSchema" mandatoryCondition="false"
+                accountid="0" password="0" purpose="PROPAGATION"/>
+  <UMappingItem id="113" extAttrName="userId" mapping_id="2"
+                intAttrName="userId" intMappingType="UserSchema" mandatoryCondition="false"
+                accountid="1" password="0" purpose="PROPAGATION"/>
+  <UMappingItem id="114" extAttrName="test3" mapping_id="2" 
+                intAttrName="fullname" intMappingType="UserSchema" mandatoryCondition="false"
+                accountid="0" password="0" purpose="PROPAGATION"/>
+    
+  <UMapping id="3" resource_name="ws-target-resource-nopropagation"/>
+  <UMappingItem id="115" mapping_id="3" extAttrName="fullname" 
+                intAttrName="fullname" intMappingType="UserSchema" mandatoryCondition="true"
+                accountid="1" password="0" purpose="PROPAGATION"/>
+                     
+  <UMapping id="4" resource_name="ws-target-resource-nopropagation2"/>
+  <UMappingItem id="116" mapping_id="4" extAttrName="fullname" 
+                intAttrName="fullname" intMappingType="UserSchema" mandatoryCondition="true"
+                accountid="1" password="0" purpose="PROPAGATION"/>
+                     
+  <UMapping id="5" resource_name="ws-target-resource-nopropagation3"/>
+  <UMappingItem id="117" mapping_id="5" extAttrName="fullname"
+                intAttrName="fullname" intMappingType="UserSchema" mandatoryCondition="true"
+                accountid="1" password="0" purpose="PROPAGATION"/>
+                     
+  <UMapping id="6" resource_name="ws-target-resource-nopropagation4"/>
+  <UMappingItem id="118" mapping_id="6"
+                extAttrName="fullname" intAttrName="fullname" intMappingType="UserSchema" mandatoryCondition="true"
+                accountid="1" password="0" purpose="PROPAGATION"/>
+                       
+  <UMapping id="7" resource_name="resource-testdb"/>
+  <UMappingItem id="119" mapping_id="7"
+                extAttrName="id" intMappingType="Username" mandatoryCondition="true"
+                accountid="1" password="0" purpose="BOTH"/>
+  <UMappingItem id="120" mapping_id="7"
+                extAttrName="__PASSWORD__" intMappingType="Password" mandatoryCondition="true"
+                accountid="0" password="1" purpose="BOTH"/>
+                     
+  <UMapping id="8" resource_name="resource-testdb2"/>
+  <UMappingItem id="121" mapping_id="8" extAttrName="id" 
+                intMappingType="Username" mandatoryCondition="true"
+                accountid="1" password="0" purpose="PROPAGATIO

<TRUNCATED>

[13/32] syncope git commit: Merge branch 'master' into 2_0_X

Posted by il...@apache.org.
Merge branch 'master' into 2_0_X


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

Branch: refs/heads/2_0_X
Commit: 20390b01e600d6294308658971e0cf7e11da35c7
Parents: ea0ab20 b907a4e
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu Jan 1 12:37:12 2015 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Jan 1 12:37:12 2015 +0100

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


http://git-wip-us.apache.org/repos/asf/syncope/blob/20390b01/pom.xml
----------------------------------------------------------------------


[21/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainSchemaValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainSchemaValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainSchemaValidator.java
new file mode 100644
index 0000000..5267785
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PlainSchemaValidator.java
@@ -0,0 +1,61 @@
+/*
+ * 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.persistence.jpa.validation.entity;
+
+import javax.validation.ConstraintValidatorContext;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+
+public class PlainSchemaValidator extends AbstractValidator<PlainSchemaCheck, PlainSchema> {
+
+    @Override
+    public boolean isValid(final PlainSchema schema, final ConstraintValidatorContext context) {
+        boolean isValid = schema.getType() != AttrSchemaType.Enum
+                || StringUtils.isNotBlank(schema.getEnumerationValues());
+        if (!isValid) {
+            context.disableDefaultConstraintViolation();
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidSchemaEnum, "Enumeration values missing")).
+                    addPropertyNode("enumerationValues").addConstraintViolation();
+        } else {
+            isValid = schema.getType() != AttrSchemaType.Encrypted
+                    || (schema.getSecretKey() != null && schema.getCipherAlgorithm() != null);
+            if (!isValid) {
+                context.disableDefaultConstraintViolation();
+                context.buildConstraintViolationWithTemplate(
+                        getTemplate(EntityViolationType.InvalidSchemaEncrypted,
+                                "SecretKey or CipherAlgorithm missing")).
+                        addPropertyNode("secretKey").addPropertyNode("cipherAlgorithm").addConstraintViolation();
+            } else {
+                isValid = !schema.isMultivalue() || !schema.isUniqueConstraint();
+                if (!isValid) {
+                    context.disableDefaultConstraintViolation();
+                    context.buildConstraintViolationWithTemplate(
+                            getTemplate(EntityViolationType.InvalidSchemaMultivalueUnique,
+                                    "Cannot contemporary be multivalue and have unique constraint")).
+                            addPropertyNode("multiValue").addConstraintViolation();
+                }
+            }
+        }
+
+        return isValid;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PolicyCheck.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PolicyCheck.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PolicyCheck.java
new file mode 100644
index 0000000..e67b662
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PolicyCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.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.persistence.validation.policy}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PolicyValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PolicyValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PolicyValidator.java
new file mode 100644
index 0000000..551bc6f
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PolicyValidator.java
@@ -0,0 +1,59 @@
+/*
+ * 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.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.persistence.api.entity.AccountPolicy;
+import org.apache.syncope.persistence.api.entity.PasswordPolicy;
+import org.apache.syncope.persistence.api.entity.Policy;
+import org.apache.syncope.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/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PropagationTaskCheck.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PropagationTaskCheck.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PropagationTaskCheck.java
new file mode 100644
index 0000000..f6d374f
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PropagationTaskCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.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 = PropagationTaskValidator.class)
+@Documented
+public @interface PropagationTaskCheck {
+
+    String message() default "{org.apache.syncope.persistence.validation.propagationtask}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PropagationTaskValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PropagationTaskValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PropagationTaskValidator.java
new file mode 100644
index 0000000..8e53c47
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/PropagationTaskValidator.java
@@ -0,0 +1,65 @@
+/*
+ * 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.persistence.jpa.validation.entity;
+
+import java.util.List;
+
+import javax.validation.ConstraintValidatorContext;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
+import org.apache.syncope.persistence.api.entity.task.PropagationTask;
+import org.apache.syncope.persistence.api.entity.task.TaskExec;
+
+public class PropagationTaskValidator extends AbstractValidator<PropagationTaskCheck, PropagationTask> {
+
+    @Override
+    public boolean isValid(final PropagationTask task, final ConstraintValidatorContext context) {
+        boolean isValid;
+
+        if (task == null) {
+            isValid = true;
+        } else {
+            isValid = task.getPropagationMode() != null
+                    && task.getPropagationOperation() != null
+                    && !task.getAttributes().isEmpty()
+                    && task.getResource() != null;
+
+            if (isValid) {
+                List<? extends TaskExec> executions = task.getExecs();
+                for (TaskExec execution : executions) {
+                    try {
+                        PropagationTaskExecStatus.valueOf(execution.getStatus());
+                    } catch (IllegalArgumentException e) {
+                        LOG.error("Invalid execution status '" + execution.getStatus() + "'", e);
+                        isValid = false;
+                    }
+                }
+            }
+
+            if (!isValid) {
+                context.disableDefaultConstraintViolation();
+                context.buildConstraintViolationWithTemplate(
+                        getTemplate(EntityViolationType.InvalidPropagationTask, "Invalid task")).
+                        addPropertyNode(task.getClass().getSimpleName()).addConstraintViolation();
+            }
+        }
+
+        return isValid;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ProvisioningTaskCheck.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ProvisioningTaskCheck.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ProvisioningTaskCheck.java
new file mode 100644
index 0000000..affc52a
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ProvisioningTaskCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.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 = ProvisioningTaskValidator.class)
+@Documented
+public @interface ProvisioningTaskCheck {
+
+    String message() default "{org.apache.syncope.persistence.validation.abstractsynctask}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ProvisioningTaskValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ProvisioningTaskValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ProvisioningTaskValidator.java
new file mode 100644
index 0000000..01d1d5d
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ProvisioningTaskValidator.java
@@ -0,0 +1,84 @@
+/*
+ * 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.persistence.jpa.validation.entity;
+
+import javax.validation.ConstraintValidatorContext;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.persistence.api.entity.task.ProvisioningTask;
+import org.apache.syncope.persistence.jpa.entity.task.JPAPushTask;
+import org.apache.syncope.persistence.jpa.entity.task.JPASyncTask;
+import org.apache.syncope.provisioning.api.sync.PushActions;
+import org.apache.syncope.provisioning.api.sync.SyncActions;
+
+public class ProvisioningTaskValidator extends AbstractValidator<ProvisioningTaskCheck, ProvisioningTask> {
+
+    private final SchedTaskValidator schedV;
+
+    public ProvisioningTaskValidator() {
+        super();
+
+        schedV = new SchedTaskValidator();
+    }
+
+    @Override
+    public boolean isValid(final ProvisioningTask object, final ConstraintValidatorContext context) {
+        boolean isValid = schedV.isValid(object, context);
+
+        if (isValid) {
+            isValid = object.getResource() != null;
+            if (!isValid) {
+                LOG.error("Resource is null");
+
+                context.disableDefaultConstraintViolation();
+                context.buildConstraintViolationWithTemplate(
+                        getTemplate(EntityViolationType.InvalidSyncTask, "Resource cannot be null")).
+                        addPropertyNode("resource").addConstraintViolation();
+            }
+
+            if (!object.getActionsClassNames().isEmpty()) {
+                for (String className : object.getActionsClassNames()) {
+                    Class<?> actionsClass = null;
+                    boolean isAssignable = false;
+                    try {
+                        actionsClass = Class.forName(className);
+                        isAssignable = object instanceof JPASyncTask
+                                ? SyncActions.class.isAssignableFrom(actionsClass)
+                                : object instanceof JPAPushTask
+                                        ? PushActions.class.isAssignableFrom(actionsClass)
+                                        : false;
+                    } catch (Exception e) {
+                        LOG.error("Invalid SyncActions specified", e);
+                        isValid = false;
+                    }
+
+                    if (actionsClass == null || !isAssignable) {
+                        isValid = false;
+
+                        context.disableDefaultConstraintViolation();
+                        context.buildConstraintViolationWithTemplate(
+                                getTemplate(EntityViolationType.InvalidSyncTask, "Invalid class name")).
+                                addPropertyNode("actionsClassName").addConstraintViolation();
+                    }
+                }
+            }
+        }
+
+        return isValid;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ReportCheck.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ReportCheck.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ReportCheck.java
new file mode 100644
index 0000000..7b18e8c
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ReportCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.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 = ReportValidator.class)
+@Documented
+public @interface ReportCheck {
+
+    String message() default "{org.apache.syncope.persistence.validation.report}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ReportValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ReportValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ReportValidator.java
new file mode 100644
index 0000000..7d2aa74
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/ReportValidator.java
@@ -0,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.persistence.jpa.validation.entity;
+
+import java.text.ParseException;
+import java.util.HashSet;
+import java.util.Set;
+import javax.validation.ConstraintValidatorContext;
+import org.apache.syncope.common.lib.report.ReportletConf;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.persistence.api.entity.Report;
+import org.quartz.CronExpression;
+
+public class ReportValidator extends AbstractValidator<ReportCheck, Report> {
+
+    @Override
+    @SuppressWarnings("ResultOfObjectAllocationIgnored")
+    public boolean isValid(final Report object, final ConstraintValidatorContext context) {
+        boolean isValid = true;
+
+        if (object.getCronExpression() != null) {
+            try {
+                new CronExpression(object.getCronExpression());
+            } catch (ParseException e) {
+                LOG.error("Invalid cron expression '" + object.getCronExpression() + "'", e);
+                isValid = false;
+
+                context.disableDefaultConstraintViolation();
+                context.buildConstraintViolationWithTemplate(
+                        getTemplate(EntityViolationType.InvalidReport, "Invalid cron expression")).
+                        addPropertyNode("cronExpression").addConstraintViolation();
+            }
+        }
+
+        Set<String> reportletNames = new HashSet<String>();
+        for (ReportletConf conf : object.getReportletConfs()) {
+            reportletNames.add(conf.getName());
+        }
+        if (reportletNames.size() != object.getReportletConfs().size()) {
+            LOG.error("Reportlet name must be unique");
+            isValid = false;
+
+            context.disableDefaultConstraintViolation();
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidReport, "Reportlet name must be unique")).
+                    addPropertyNode("reportletConfs").addConstraintViolation();
+        }
+
+        return isValid;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/RoleCheck.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/RoleCheck.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/RoleCheck.java
new file mode 100644
index 0000000..fc9d958
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/RoleCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.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 = RoleValidator.class)
+@Documented
+public @interface RoleCheck {
+
+    String message() default "{org.apache.syncope.persistence.validation.syncoperole}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/RoleValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/RoleValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/RoleValidator.java
new file mode 100644
index 0000000..a946b30
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/RoleValidator.java
@@ -0,0 +1,44 @@
+/*
+ * 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.persistence.jpa.validation.entity;
+
+import javax.validation.ConstraintValidatorContext;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.persistence.api.entity.role.Role;
+
+public class RoleValidator extends AbstractValidator<RoleCheck, Role> {
+
+    @Override
+    public boolean isValid(final Role object, final ConstraintValidatorContext context) {
+        context.disableDefaultConstraintViolation();
+
+        boolean isValid = true;
+
+        if (object.getUserOwner() != null && object.getRoleOwner() != null) {
+            isValid = false;
+
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidRoleOwner,
+                            "A role must either be owned by an user or a role, not both")).
+                    addPropertyNode("owner").addConstraintViolation();
+        }
+
+        return isValid;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/SchedTaskCheck.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/SchedTaskCheck.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/SchedTaskCheck.java
new file mode 100644
index 0000000..2b67e4b
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/SchedTaskCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.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 = SchedTaskValidator.class)
+@Documented
+public @interface SchedTaskCheck {
+
+    String message() default "{org.apache.syncope.persistence.validation.schedtask}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/SchedTaskValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/SchedTaskValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/SchedTaskValidator.java
new file mode 100644
index 0000000..2591b94
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/SchedTaskValidator.java
@@ -0,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.persistence.jpa.validation.entity;
+
+import java.text.ParseException;
+
+import javax.validation.ConstraintValidatorContext;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.persistence.api.entity.task.SchedTask;
+import org.quartz.CronExpression;
+import org.quartz.Job;
+
+public class SchedTaskValidator extends AbstractValidator<SchedTaskCheck, SchedTask> {
+
+    @Override
+    public boolean isValid(final SchedTask object, final ConstraintValidatorContext context) {
+        boolean isValid;
+
+        Class<?> jobClass = null;
+        try {
+            jobClass = Class.forName(object.getJobClassName());
+            isValid = Job.class.isAssignableFrom(jobClass);
+        } catch (Exception e) {
+            LOG.error("Invalid Job class specified", e);
+            isValid = false;
+        }
+        if (jobClass == null || !isValid) {
+            isValid = false;
+
+            context.disableDefaultConstraintViolation();
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidSchedTask, "Invalid job class name")).
+                    addPropertyNode("jobClassName").addConstraintViolation();
+        }
+
+        if (isValid && object.getCronExpression() != null) {
+            try {
+                new CronExpression(object.getCronExpression());
+            } catch (ParseException e) {
+                LOG.error("Invalid cron expression '" + object.getCronExpression() + "'", e);
+                isValid = false;
+
+                context.disableDefaultConstraintViolation();
+                context.buildConstraintViolationWithTemplate(
+                        getTemplate(EntityViolationType.InvalidSchedTask, "Invalid cron expression")).
+                        addPropertyNode("cronExpression").addConstraintViolation();
+            }
+        }
+
+        return isValid;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/SchemaNameCheck.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/SchemaNameCheck.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/SchemaNameCheck.java
new file mode 100644
index 0000000..b445c79
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/SchemaNameCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.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 = SchemaNameValidator.class)
+@Documented
+public @interface SchemaNameCheck {
+
+    String message() default "{org.apache.syncope.persistence.validation.schema}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/SchemaNameValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/SchemaNameValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/SchemaNameValidator.java
new file mode 100644
index 0000000..eda316d
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/SchemaNameValidator.java
@@ -0,0 +1,133 @@
+/*
+ * 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.persistence.jpa.validation.entity;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import javax.validation.ConstraintValidatorContext;
+import org.apache.commons.lang3.ClassUtils;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.persistence.api.entity.conf.CPlainSchema;
+import org.apache.syncope.persistence.api.entity.membership.MDerSchema;
+import org.apache.syncope.persistence.api.entity.membership.MPlainSchema;
+import org.apache.syncope.persistence.api.entity.membership.MVirSchema;
+import org.apache.syncope.persistence.api.entity.role.RDerSchema;
+import org.apache.syncope.persistence.api.entity.role.RPlainSchema;
+import org.apache.syncope.persistence.api.entity.role.RVirSchema;
+import org.apache.syncope.persistence.api.entity.user.UDerSchema;
+import org.apache.syncope.persistence.api.entity.user.UPlainSchema;
+import org.apache.syncope.persistence.api.entity.user.UVirSchema;
+import org.apache.syncope.persistence.jpa.entity.conf.JPAConf;
+import org.apache.syncope.persistence.jpa.entity.membership.JPAMembership;
+import org.apache.syncope.persistence.jpa.entity.role.JPARole;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUser;
+
+public class SchemaNameValidator extends AbstractValidator<SchemaNameCheck, Object> {
+
+    private static final List<String> UNALLOWED_USCHEMA_NAMES = new ArrayList<>();
+
+    private static final List<String> UNALLOWED_MSCHEMA_NAMES = new ArrayList<>();
+
+    private static final List<String> UNALLOWED_RSCHEMA_NAMES = new ArrayList<>();
+
+    private static final List<String> UNALLOWED_CSCHEMA_NAMES = new ArrayList<>();
+
+    static {
+        initUnallowedSchemaNames(JPAUser.class, UNALLOWED_USCHEMA_NAMES);
+        initUnallowedSchemaNames(JPAMembership.class, UNALLOWED_MSCHEMA_NAMES);
+        initUnallowedSchemaNames(JPARole.class, UNALLOWED_RSCHEMA_NAMES);
+        initUnallowedSchemaNames(JPAConf.class, UNALLOWED_CSCHEMA_NAMES);
+    }
+
+    private static void initUnallowedSchemaNames(final Class<?> entityClass, final List<String> names) {
+        List<Class<?>> classes = ClassUtils.getAllSuperclasses(entityClass);
+        classes.add(JPAUser.class);
+        for (Class<?> clazz : classes) {
+            for (Field field : clazz.getDeclaredFields()) {
+                if (!Collection.class.isAssignableFrom(field.getType())
+                        && !Map.class.isAssignableFrom(field.getType())) {
+
+                    names.add(field.getName());
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean isValid(final Object object, final ConstraintValidatorContext context) {
+        final String schemaName;
+        final List<String> unallowedNames;
+
+        if (object instanceof UPlainSchema) {
+            schemaName = ((UPlainSchema) object).getKey();
+            unallowedNames = UNALLOWED_USCHEMA_NAMES;
+        } else if (object instanceof UDerSchema) {
+            schemaName = ((UDerSchema) object).getKey();
+            unallowedNames = UNALLOWED_USCHEMA_NAMES;
+        } else if (object instanceof UVirSchema) {
+            schemaName = ((UVirSchema) object).getKey();
+            unallowedNames = UNALLOWED_USCHEMA_NAMES;
+        } else if (object instanceof MPlainSchema) {
+            schemaName = ((MPlainSchema) object).getKey();
+            unallowedNames = UNALLOWED_MSCHEMA_NAMES;
+        } else if (object instanceof MDerSchema) {
+            schemaName = ((MDerSchema) object).getKey();
+            unallowedNames = UNALLOWED_MSCHEMA_NAMES;
+        } else if (object instanceof MVirSchema) {
+            schemaName = ((MVirSchema) object).getKey();
+            unallowedNames = UNALLOWED_MSCHEMA_NAMES;
+        } else if (object instanceof RPlainSchema) {
+            schemaName = ((RPlainSchema) object).getKey();
+            unallowedNames = UNALLOWED_RSCHEMA_NAMES;
+        } else if (object instanceof RDerSchema) {
+            schemaName = ((RDerSchema) object).getKey();
+            unallowedNames = UNALLOWED_RSCHEMA_NAMES;
+        } else if (object instanceof RVirSchema) {
+            schemaName = ((RVirSchema) object).getKey();
+            unallowedNames = UNALLOWED_RSCHEMA_NAMES;
+        } else if (object instanceof CPlainSchema) {
+            schemaName = ((CPlainSchema) object).getKey();
+            unallowedNames = UNALLOWED_CSCHEMA_NAMES;
+        } else {
+            schemaName = null;
+            unallowedNames = Collections.emptyList();
+        }
+
+        boolean isValid = NAME_PATTERN.matcher(schemaName).matches();
+        if (!isValid) {
+            context.disableDefaultConstraintViolation();
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidName, "Invalid Schema name")).
+                    addPropertyNode("name").addConstraintViolation();
+        } else if (unallowedNames.contains(schemaName)) {
+            context.disableDefaultConstraintViolation();
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidName, "Schema name not allowed: " + schemaName)).
+                    addPropertyNode("name").addConstraintViolation();
+
+            return false;
+        }
+
+        return isValid;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/UserCheck.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/UserCheck.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/UserCheck.java
new file mode 100644
index 0000000..854d4dd
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/UserCheck.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.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 = UserValidator.class)
+@Documented
+public @interface UserCheck {
+
+    String message() default "{org.apache.syncope.persistence.validation.syncopeuser}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/UserValidator.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/UserValidator.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/UserValidator.java
new file mode 100644
index 0000000..5ef6917
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/validation/entity/UserValidator.java
@@ -0,0 +1,194 @@
+/*
+ * 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.persistence.jpa.validation.entity;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.annotation.Resource;
+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.persistence.api.dao.PolicyDAO;
+import org.apache.syncope.persistence.api.entity.AccountPolicy;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.PasswordPolicy;
+import org.apache.syncope.persistence.api.entity.Policy;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.server.utils.policy.AccountPolicyEnforcer;
+import org.apache.syncope.server.utils.policy.AccountPolicyException;
+import org.apache.syncope.server.utils.policy.PasswordPolicyEnforcer;
+import org.apache.syncope.server.utils.policy.PolicyEvaluator;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class UserValidator extends AbstractValidator<UserCheck, User> {
+
+    @Resource(name = "adminUser")
+    private String adminUser;
+
+    @Resource(name = "anonymousUser")
+    private String anonymousUser;
+
+    @Autowired
+    private PolicyDAO policyDAO;
+
+    @Autowired
+    private PolicyEvaluator evaluator;
+
+    @Autowired
+    private PasswordPolicyEnforcer ppEnforcer;
+
+    @Autowired
+    private AccountPolicyEnforcer apEnforcer;
+
+    @Override
+    public boolean isValid(final User user, final ConstraintValidatorContext context) {
+        context.disableDefaultConstraintViolation();
+
+        // ------------------------------
+        // Verify password policies
+        // ------------------------------
+        LOG.debug("Password Policy enforcement");
+
+        try {
+            int maxPPSpecHistory = 0;
+            for (Policy policy : getPasswordPolicies(user)) {
+                // evaluate policy
+                final PasswordPolicySpec ppSpec = evaluator.evaluate(policy, user);
+                // enforce policy
+                ppEnforcer.enforce(ppSpec, policy.getType(), user);
+
+                if (ppSpec.getHistoryLength() > maxPPSpecHistory) {
+                    maxPPSpecHistory = ppSpec.getHistoryLength();
+                }
+            }
+
+            // update user's password history with encrypted password
+            if (maxPPSpecHistory > 0 && user.getPassword() != null) {
+                user.getPasswordHistory().add(user.getPassword());
+            }
+            // keep only the last maxPPSpecHistory items in user's password history
+            if (maxPPSpecHistory < user.getPasswordHistory().size()) {
+                for (int i = 0; i < user.getPasswordHistory().size() - maxPPSpecHistory; i++) {
+                    user.getPasswordHistory().remove(i);
+                }
+            }
+        } catch (Exception e) {
+            LOG.debug("Invalid password");
+
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidPassword, e.getMessage())).
+                    addPropertyNode("password").addConstraintViolation();
+
+            return false;
+        } finally {
+            // password has been validated, let's remove its clear version
+            user.removeClearPassword();
+        }
+        // ------------------------------
+
+        // ------------------------------
+        // Verify account policies
+        // ------------------------------
+        LOG.debug("Account Policy enforcement");
+
+        try {
+            if (adminUser.equals(user.getUsername()) || anonymousUser.equals(user.getUsername())) {
+                throw new AccountPolicyException("Not allowed: " + user.getUsername());
+            }
+
+            // invalid username
+            for (Policy policy : getAccountPolicies(user)) {
+                // evaluate policy
+                final AccountPolicySpec accountPolicy = evaluator.evaluate(policy, user);
+
+                // enforce policy
+                apEnforcer.enforce(accountPolicy, policy.getType(), user);
+            }
+        } catch (Exception e) {
+            LOG.debug("Invalid username");
+
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidUsername, e.getMessage())).
+                    addPropertyNode("username").addConstraintViolation();
+
+            return false;
+        }
+        // ------------------------------
+
+        return true;
+    }
+
+    private List<PasswordPolicy> getPasswordPolicies(final User user) {
+        final List<PasswordPolicy> policies = new ArrayList<>();
+
+        // Add global policy
+        PasswordPolicy policy = policyDAO.getGlobalPasswordPolicy();
+        if (policy != null) {
+            policies.add(policy);
+        }
+
+        // add resource policies
+        for (ExternalResource resource : user.getResources()) {
+            policy = resource.getPasswordPolicy();
+            if (policy != null) {
+                policies.add(policy);
+            }
+        }
+
+        // add role policies
+        for (Role role : user.getRoles()) {
+            policy = role.getPasswordPolicy();
+            if (policy != null) {
+                policies.add(policy);
+            }
+        }
+
+        return policies;
+    }
+
+    private List<AccountPolicy> getAccountPolicies(final User user) {
+        final List<AccountPolicy> policies = new ArrayList<>();
+
+        // add global policy
+        AccountPolicy policy = policyDAO.getGlobalAccountPolicy();
+        if (policy != null) {
+            policies.add(policy);
+        }
+
+        // add resource policies
+        for (ExternalResource resource : user.getResources()) {
+            policy = resource.getAccountPolicy();
+            if (policy != null) {
+                policies.add(policy);
+            }
+        }
+
+        // add role policies
+        for (Role role : user.getRoles()) {
+            policy = role.getAccountPolicy();
+            if (policy != null) {
+                policies.add(policy);
+            }
+        }
+
+        return policies;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/resources/META-INF/orm.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/META-INF/orm.xml b/syncope620/server/persistence-jpa/src/main/resources/META-INF/orm.xml
new file mode 100644
index 0000000..4ea467f
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/resources/META-INF/orm.xml
@@ -0,0 +1,355 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
+                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm 
+                                     http://java.sun.com/xml/ns/persistence/orm_2_0.xsd"
+                 version="2.0">
+  
+  <persistence-unit-metadata>
+    <persistence-unit-defaults>
+      <entity-listeners>
+        <entity-listener class="org.apache.syncope.persistence.jpa.validation.entity.EntityValidationListener">
+          <pre-persist method-name="validate"/>
+          <pre-update method-name="validate"/>
+        </entity-listener>
+      </entity-listeners>
+    </persistence-unit-defaults>
+  </persistence-unit-metadata>
+  
+  <table-generator name="SEQ_UPlainAttrValue" pk-column-value="SEQ_UPlainAttrValue" initial-value="100"/>
+  <table-generator name="SEQ_RPlainAttrValue" pk-column-value="SEQ_RPlainAttrValue" initial-value="100"/>
+  <table-generator name="SEQ_MAttrPlainValue" pk-column-value="SEQ_MAttrPlainValue" initial-value="100"/>
+  <table-generator name="SEQ_CAttrPlainValue" pk-column-value="SEQ_CAttrPlainValue" initial-value="100"/>
+
+  <entity class="org.apache.syncope.persistence.jpa.entity.user.JPAUser">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_User" strategy="TABLE"/>
+        <table-generator name="SEQ_User" pk-column-value="SEQ_User" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>
+
+  <entity class="org.apache.syncope.persistence.jpa.entity.role.JPARole">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_Role" strategy="TABLE"/>
+        <table-generator name="SEQ_Role" pk-column-value="SEQ_Role" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>
+
+  <entity class="org.apache.syncope.persistence.jpa.entity.membership.JPAMembership">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_Membership" strategy="TABLE"/>
+        <table-generator name="SEQ_Membership" pk-column-value="SEQ_Membership" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>
+
+  <entity class="org.apache.syncope.persistence.jpa.entity.user.JPAUMapping">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_UMapping" strategy="TABLE"/>
+        <table-generator name="SEQ_UMapping" pk-column-value="SEQ_UMapping" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.persistence.jpa.entity.role.JPARMapping">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_RMapping" strategy="TABLE"/>
+        <table-generator name="SEQ_RMapping" pk-column-value="SEQ_RMapping" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.persistence.jpa.entity.user.JPAUMappingItem">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_UMappingItem" strategy="TABLE"/>
+        <table-generator name="SEQ_UMappingItem" pk-column-value="SEQ_UMappingItem" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.persistence.jpa.entity.role.JPARMappingItem">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_RMappingItem" strategy="TABLE"/>
+        <table-generator name="SEQ_RMappingItem" pk-column-value="SEQ_RMappingItem" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+
+  <entity class="org.apache.syncope.persistence.jpa.entity.JPAConnInstance">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_ConnInstance" strategy="TABLE"/>
+        <table-generator name="SEQ_ConnInstance" pk-column-value="SEQ_ConnInstance" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+
+  <entity class="org.apache.syncope.persistence.jpa.entity.user.JPAUPlainAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_UPlainAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_UPlainAttr" pk-column-value="SEQ_UPlainAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.persistence.jpa.entity.role.JPARPlainAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_RPlainAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_RPlainAttr" pk-column-value="SEQ_RPlainAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.persistence.jpa.entity.membership.JPAMPlainAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_MAttrPlain" strategy="TABLE"/>
+        <table-generator name="SEQ_MAttrPlain" pk-column-value="SEQ_MAttrPlain" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.persistence.jpa.entity.conf.JPACPlainAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_CAttrPlain" strategy="TABLE"/>
+        <table-generator name="SEQ_CAttrPlain" pk-column-value="SEQ_CAttrPlain" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+    
+  <entity class="org.apache.syncope.persistence.jpa.entity.user.JPAUPlainAttrValue">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_UPlainAttrValue" strategy="TABLE"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.persistence.jpa.entity.user.JPAUPlainAttrUniqueValue">
+    <table>
+      <unique-constraint>
+        <column-name>booleanValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+      <unique-constraint>
+        <column-name>dateValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+      <unique-constraint>
+        <column-name>stringValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+      <unique-constraint>
+        <column-name>doubleValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+      <unique-constraint>
+        <column-name>longValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+    </table>
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_UPlainAttrValue" strategy="TABLE"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.persistence.jpa.entity.role.JPARPlainAttrValue">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_RPlainAttrValue" strategy="TABLE"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.persistence.jpa.entity.role.JPARPlainAttrUniqueValue">
+    <table>
+      <unique-constraint>
+        <column-name>booleanValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+      <unique-constraint>
+        <column-name>dateValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+      <unique-constraint>
+        <column-name>stringValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+      <unique-constraint>
+        <column-name>doubleValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+      <unique-constraint>
+        <column-name>longValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+    </table>
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_RPlainAttrValue" strategy="TABLE"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.persistence.jpa.entity.membership.JPAMPlainAttrValue">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_MAttrPlainValue" strategy="TABLE"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.persistence.jpa.entity.membership.JPAMPlainAttrUniqueValue">
+    <table>
+      <unique-constraint>
+        <column-name>booleanValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+      <unique-constraint>
+        <column-name>dateValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+      <unique-constraint>
+        <column-name>stringValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+      <unique-constraint>
+        <column-name>doubleValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+      <unique-constraint>
+        <column-name>longValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+    </table>
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_MAttrPlainValue" strategy="TABLE"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.persistence.jpa.entity.conf.JPACPlainAttrValue">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_CAttrPlainValue" strategy="TABLE"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.persistence.jpa.entity.conf.JPACPlainAttrUniqueValue">
+    <table>
+      <unique-constraint>
+        <column-name>booleanValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+      <unique-constraint>
+        <column-name>dateValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+      <unique-constraint>
+        <column-name>stringValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+      <unique-constraint>
+        <column-name>doubleValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+      <unique-constraint>
+        <column-name>longValue</column-name>
+        <column-name>schema_name</column-name>
+      </unique-constraint>
+    </table>
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_CAttrPlainValue" strategy="TABLE"/>
+      </id>
+    </attributes>
+  </entity>
+
+  <entity class="org.apache.syncope.persistence.jpa.entity.task.JPATask">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_Task" strategy="TABLE"/>
+        <table-generator name="SEQ_Task" pk-column-value="SEQ_Task" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.persistence.jpa.entity.task.JPATaskExec">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_TaskExec" strategy="TABLE"/>
+        <table-generator name="SEQ_TaskExec" pk-column-value="SEQ_TaskExec" initial-value="10"/>
+      </id>
+    </attributes>
+  </entity>
+    
+  <entity class="org.apache.syncope.persistence.jpa.entity.JPAPolicy">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_Policy" strategy="TABLE"/>
+        <table-generator name="SEQ_Policy" pk-column-value="SEQ_Policy" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+
+  <entity class="org.apache.syncope.persistence.jpa.entity.JPAReport">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_Report" strategy="TABLE"/>
+        <table-generator name="SEQ_Report" pk-column-value="SEQ_Report" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.persistence.jpa.entity.JPAReportExec">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_ReportExec" strategy="TABLE"/>
+        <table-generator name="SEQ_ReportExec" pk-column-value="SEQ_ReportExec" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.persistence.jpa.entity.JPAReportletConfInstance">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_ReportletConfInstance" strategy="TABLE"/>
+        <table-generator name="SEQ_ReportletConfInstance" pk-column-value="SEQ_ReportletConfInstance" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.persistence.jpa.entity.JPANotification">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_Notification" strategy="TABLE"/>
+        <table-generator name="SEQ_Notification" pk-column-value="SEQ_Notification" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.persistence.jpa.entity.JPASecurityQuestion">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_SecurityQuestion" strategy="TABLE"/>
+        <table-generator name="SEQ_SecurityQuestion" pk-column-value="SEQ_SecurityQuestion" initial-value="100"/>
+      </id>
+    </attributes>
+  </entity>
+</entity-mappings>

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/resources/META-INF/spring-persistence.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/META-INF/spring-persistence.xml b/syncope620/server/persistence-jpa/src/main/resources/META-INF/spring-persistence.xml
new file mode 100644
index 0000000..d668353
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/resources/META-INF/spring-persistence.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
+                                 http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
+             version="2.0">
+  
+  <persistence-unit name="syncopePersistenceUnit">
+    <mapping-file>META-INF/orm.xml</mapping-file>
+    <validation-mode>NONE</validation-mode>    
+  </persistence-unit>
+  
+</persistence>

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/resources/audit/audit.sql
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/audit/audit.sql b/syncope620/server/persistence-jpa/src/main/resources/audit/audit.sql
new file mode 100644
index 0000000..faf8c5b
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/resources/audit/audit.sql
@@ -0,0 +1,24 @@
+-- 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.
+
+CREATE TABLE IF NOT EXISTS SYNCOPEAUDIT (
+  EVENT_DATE TIMESTAMP,
+  LOGGER_LEVEL VARCHAR(255) NOT NULL,
+  LOGGER VARCHAR(255) NOT NULL,
+  MESSAGE TEXT NOT NULL,
+  THROWABLE TEXT
+)

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/resources/audit/audit_mysql_innodb.sql
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/audit/audit_mysql_innodb.sql b/syncope620/server/persistence-jpa/src/main/resources/audit/audit_mysql_innodb.sql
new file mode 100644
index 0000000..ff753fa
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/resources/audit/audit_mysql_innodb.sql
@@ -0,0 +1,24 @@
+-- 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.
+
+CREATE TABLE IF NOT EXISTS SYNCOPEAUDIT (
+  EVENT_DATE TIMESTAMP,
+  LOGGER_LEVEL VARCHAR(255) NOT NULL,
+  LOGGER VARCHAR(255) NOT NULL,
+  MESSAGE TEXT NOT NULL,
+  THROWABLE TEXT
+) ENGINE=InnoDB

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/resources/audit/audit_oracle.sql
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/audit/audit_oracle.sql b/syncope620/server/persistence-jpa/src/main/resources/audit/audit_oracle.sql
new file mode 100644
index 0000000..e1b7d81
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/resources/audit/audit_oracle.sql
@@ -0,0 +1,38 @@
+-- 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.
+
+BEGIN
+    BEGIN
+         EXECUTE IMMEDIATE 'DROP TABLE SYNCOPEAUDIT';
+    EXCEPTION
+         WHEN OTHERS THEN
+                IF SQLCODE != -942 THEN
+                     RAISE;
+                END IF;
+    END;
+
+    EXECUTE IMMEDIATE '
+CREATE TABLE SYNCOPEAUDIT (
+  EVENT_DATE TIMESTAMP,
+  LOGGER_LEVEL VARCHAR(255) NOT NULL,
+  LOGGER VARCHAR(255) NOT NULL,
+  MESSAGE CLOB NOT NULL,
+  THROWABLE CLOB
+)
+';
+
+END;

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/resources/audit/audit_sqlserver.sql
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/resources/audit/audit_sqlserver.sql b/syncope620/server/persistence-jpa/src/main/resources/audit/audit_sqlserver.sql
new file mode 100644
index 0000000..191428a
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/resources/audit/audit_sqlserver.sql
@@ -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.
+
+IF NOT EXISTS
+(SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[SYNCOPEAUDIT]') AND type in (N'U'))
+BEGIN
+CREATE TABLE SYNCOPEAUDIT (
+  EVENT_DATE DATETIME,
+  LOGGER_LEVEL VARCHAR(255) NOT NULL,
+  LOGGER VARCHAR(255) NOT NULL,
+  MESSAGE TEXT NOT NULL,
+  THROWABLE TEXT
+)
+END


[05/32] syncope git commit: Minor stuff

Posted by il...@apache.org.
Minor stuff


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

Branch: refs/heads/2_0_X
Commit: 62faf634c469ef60a2ba2cc53a52e7b16a2ec462
Parents: c73a73b
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Wed Dec 24 09:20:24 2014 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Wed Dec 24 09:20:24 2014 +0100

----------------------------------------------------------------------
 .../src/main/java/org/apache/syncope/common/SyncopeConstants.java  | 2 +-
 core/src/test/java/org/apache/syncope/core/AbstractTest.java       | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/62faf634/common/src/main/java/org/apache/syncope/common/SyncopeConstants.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/syncope/common/SyncopeConstants.java b/common/src/main/java/org/apache/syncope/common/SyncopeConstants.java
index a502656..c729cdd 100644
--- a/common/src/main/java/org/apache/syncope/common/SyncopeConstants.java
+++ b/common/src/main/java/org/apache/syncope/common/SyncopeConstants.java
@@ -22,7 +22,7 @@ import java.util.regex.Pattern;
 
 public class SyncopeConstants {
 
-    public static final String NAMESPACE = "http://syncope.apache.org/1.2";
+    public static final String NAMESPACE = "http://syncope.apache.org/2.0";
 
     public static final String UNAUTHENTICATED = "unauthenticated";
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/62faf634/core/src/test/java/org/apache/syncope/core/AbstractTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/syncope/core/AbstractTest.java b/core/src/test/java/org/apache/syncope/core/AbstractTest.java
index 1f2e840..66fc495 100644
--- a/core/src/test/java/org/apache/syncope/core/AbstractTest.java
+++ b/core/src/test/java/org/apache/syncope/core/AbstractTest.java
@@ -24,7 +24,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.util.Properties;
 import org.apache.commons.io.IOUtils;
-import org.apache.syncope.core.util.ConnIdBundleManager;
 import org.junit.BeforeClass;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;


[12/32] syncope git commit: Merge branch '1_2_X'

Posted by il...@apache.org.
Merge branch '1_2_X'


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

Branch: refs/heads/2_0_X
Commit: b907a4e0612c2dc914afeea6f22ad4bdbfc55f74
Parents: 08893dc 257be98
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu Jan 1 12:35:18 2015 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Jan 1 12:35:18 2015 +0100

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


http://git-wip-us.apache.org/repos/asf/syncope/blob/b907a4e0/pom.xml
----------------------------------------------------------------------


[24/32] syncope git commit: [SYNCOPE-620] JPA entities + basic tests

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAPasswordPolicy.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAPasswordPolicy.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAPasswordPolicy.java
new file mode 100644
index 0000000..1f0ee3a
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAPasswordPolicy.java
@@ -0,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.persistence.jpa.entity;
+
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.Entity;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.syncope.persistence.api.entity.PasswordPolicy;
+
+@Entity
+@DiscriminatorValue("PasswordPolicy")
+public class JPAPasswordPolicy extends JPAPolicy implements PasswordPolicy {
+
+    private static final long serialVersionUID = 9138550910385232849L;
+
+    public JPAPasswordPolicy() {
+        this(false);
+    }
+
+    public JPAPasswordPolicy(boolean global) {
+        super();
+
+        this.type = global
+                ? PolicyType.GLOBAL_PASSWORD
+                : PolicyType.PASSWORD;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAPolicy.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAPolicy.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAPolicy.java
new file mode 100644
index 0000000..af0ab0a
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAPolicy.java
@@ -0,0 +1,90 @@
+/*
+ * 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.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.PolicySpec;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.syncope.persistence.api.entity.Policy;
+import org.apache.syncope.persistence.jpa.validation.entity.PolicyCheck;
+import org.apache.syncope.server.utils.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;
+
+    public static final String TABLE = "Policy";
+
+    @Id
+    private Long id;
+
+    @NotNull
+    private String description;
+
+    @NotNull
+    @Enumerated(EnumType.STRING)
+    protected PolicyType type;
+
+    @Lob
+    private 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;
+    }
+
+    @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/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAPushPolicy.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAPushPolicy.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAPushPolicy.java
new file mode 100644
index 0000000..1a661a9
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAPushPolicy.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.persistence.jpa.entity;
+
+import javax.persistence.Entity;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.syncope.persistence.api.entity.PushPolicy;
+
+@Entity
+public class JPAPushPolicy extends JPAPolicy implements PushPolicy {
+
+    private static final long serialVersionUID = -6090413855809521279L;
+
+    public JPAPushPolicy() {
+        this(false);
+    }
+
+    public JPAPushPolicy(final boolean global) {
+        super();
+
+        this.type = global
+                ? PolicyType.GLOBAL_PUSH
+                : PolicyType.PUSH;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAReport.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAReport.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAReport.java
new file mode 100644
index 0000000..3fcdd63
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAReport.java
@@ -0,0 +1,150 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import org.apache.syncope.common.lib.report.ReportletConf;
+import org.apache.syncope.persistence.api.entity.Report;
+import org.apache.syncope.persistence.api.entity.ReportExec;
+import org.apache.syncope.persistence.jpa.validation.entity.ReportCheck;
+
+@Entity
+@Table(name = JPAReport.TABLE)
+@ReportCheck
+public class JPAReport extends AbstractEntity<Long> implements Report {
+
+    private static final long serialVersionUID = -587652654964285834L;
+
+    public static final String TABLE = "Report";
+
+    @Id
+    private Long id;
+
+    @Column(unique = true, nullable = false)
+    private String name;
+
+    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "report")
+    private List<JPAReportletConfInstance> reportletConfs;
+
+    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<>();
+    }
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    @Override
+    public boolean addExec(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) {
+        checkType(exec, JPAReportExec.class);
+        return exec != null && executions.remove((JPAReportExec) exec);
+    }
+
+    @Override
+    public List<? extends ReportExec> getExecs() {
+        return executions;
+    }
+
+    @Override
+    public boolean addReportletConf(final ReportletConf reportletConf) {
+        if (reportletConf == null) {
+            return false;
+        }
+
+        JPAReportletConfInstance instance = new JPAReportletConfInstance();
+        instance.setReport(this);
+        instance.setInstance(reportletConf);
+
+        return reportletConfs.add(instance);
+    }
+
+    @Override
+    public boolean removeReportletConf(final ReportletConf reportletConf) {
+        if (reportletConf == null) {
+            return false;
+        }
+
+        checkType(reportletConf, JPAReportletConfInstance.class);
+
+        JPAReportletConfInstance found = null;
+        for (JPAReportletConfInstance instance : reportletConfs) {
+            if (reportletConf.equals(instance.getInstance())) {
+                found = instance;
+            }
+        }
+
+        return found == null
+                ? false
+                : reportletConfs.remove(found);
+    }
+
+    @Override
+    public List<ReportletConf> getReportletConfs() {
+        List<ReportletConf> result = new ArrayList<>(reportletConfs.size());
+
+        for (JPAReportletConfInstance instance : reportletConfs) {
+            result.add(instance.getInstance());
+        }
+
+        return result;
+    }
+
+    @Override
+    public String getCronExpression() {
+        return cronExpression;
+    }
+
+    @Override
+    public void setCronExpression(final String cronExpression) {
+        this.cronExpression = cronExpression;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAReportExec.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAReportExec.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAReportExec.java
new file mode 100644
index 0000000..9f9be18
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAReportExec.java
@@ -0,0 +1,87 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import javax.persistence.Basic;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.Lob;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.syncope.common.lib.types.ReportExecStatus;
+import org.apache.syncope.persistence.api.entity.Report;
+import org.apache.syncope.persistence.api.entity.ReportExec;
+
+@Entity
+@Table(name = JPAReportExec.TABLE)
+public class JPAReportExec extends AbstractExec implements ReportExec {
+
+    private static final long serialVersionUID = -6178274296037547769L;
+
+    public static final String TABLE = "ReportExec";
+
+    @Id
+    private Long id;
+
+    /**
+     * The referred report.
+     */
+    @ManyToOne(optional = false)
+    private JPAReport report;
+
+    /**
+     * Report execution result, stored as an XML stream.
+     */
+    @Lob
+    @Basic(fetch = FetchType.LAZY)
+    private Byte[] execResult;
+
+    @Override
+    public Long getKey() {
+        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 byte[] getExecResult() {
+        return execResult == null ? null : ArrayUtils.toPrimitive(execResult);
+    }
+
+    @Override
+    public void setExecResult(final byte[] execResult) {
+        this.execResult = execResult == null ? null : ArrayUtils.toObject(execResult);
+    }
+
+    @Override
+    public void setStatus(final ReportExecStatus status) {
+        super.setStatus(status.name());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAReportletConfInstance.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAReportletConfInstance.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAReportletConfInstance.java
new file mode 100644
index 0000000..dbe3cf2
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPAReportletConfInstance.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.persistence.jpa.entity;
+
+import org.apache.syncope.persistence.api.entity.ReportletConfInstance;
+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.report.ReportletConf;
+import org.apache.syncope.persistence.api.entity.Report;
+import org.apache.syncope.server.utils.serialization.POJOHelper;
+
+@Entity
+@Table(name = JPAReportletConfInstance.TABLE)
+public class JPAReportletConfInstance extends AbstractEntity<Long> implements ReportletConfInstance {
+
+    private static final long serialVersionUID = -2436055132955674610L;
+
+    public static final String TABLE = "ReportletConfInstance";
+
+    @Id
+    private Long id;
+
+    @Lob
+    private String serializedInstance;
+
+    @ManyToOne
+    private JPAReport report;
+
+    @Override
+    public Long getKey() {
+        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
+                : POJOHelper.serialize(instance);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPASecurityQuestion.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPASecurityQuestion.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPASecurityQuestion.java
new file mode 100644
index 0000000..bfe76bc
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPASecurityQuestion.java
@@ -0,0 +1,56 @@
+/*
+ * 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.persistence.jpa.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.user.SecurityQuestion;
+
+@Entity
+@Table(name = JPASecurityQuestion.TABLE)
+public class JPASecurityQuestion extends AbstractEntity<Long> implements SecurityQuestion {
+
+    private static final long serialVersionUID = -7646140284033489392L;
+
+    public static final String TABLE = "SecurityQuestion";
+
+    @Id
+    private Long id;
+
+    @Column(unique = true)
+    private String content;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public String getContent() {
+        return content;
+    }
+
+    @Override
+    public void setContent(final String content) {
+        this.content = content;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPASyncPolicy.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPASyncPolicy.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPASyncPolicy.java
new file mode 100644
index 0000000..d78425b
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/JPASyncPolicy.java
@@ -0,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.persistence.jpa.entity;
+
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.Entity;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.syncope.persistence.api.entity.SyncPolicy;
+
+@Entity
+@DiscriminatorValue("SyncPolicy")
+public class JPASyncPolicy extends JPAPolicy implements SyncPolicy {
+
+    private static final long serialVersionUID = -6090413855809521279L;
+
+    public JPASyncPolicy() {
+        this(false);
+    }
+
+    public JPASyncPolicy(final boolean global) {
+        super();
+
+        this.type = global
+                ? PolicyType.GLOBAL_SYNC
+                : PolicyType.SYNC;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPACPlainAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPACPlainAttr.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPACPlainAttr.java
new file mode 100644
index 0000000..74c7d66
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPACPlainAttr.java
@@ -0,0 +1,150 @@
+/*
+ * 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.persistence.jpa.entity.conf;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.validation.Valid;
+import org.apache.syncope.persistence.api.entity.Attributable;
+import org.apache.syncope.persistence.api.entity.PlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.apache.syncope.persistence.api.entity.conf.CPlainAttr;
+import org.apache.syncope.persistence.api.entity.conf.CPlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.conf.CPlainAttrValue;
+import org.apache.syncope.persistence.api.entity.conf.CPlainSchema;
+import org.apache.syncope.persistence.api.entity.conf.Conf;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainAttr;
+
+/**
+ * Configuration attribute.
+ */
+@Entity
+@Table(name = JPACPlainAttr.TABLE)
+public class JPACPlainAttr extends AbstractPlainAttr implements CPlainAttr {
+
+    private static final long serialVersionUID = 6333601983691157406L;
+
+    public static final String TABLE = "CPlainAttr";
+
+    /**
+     * Auto-generated id for this table.
+     */
+    @Id
+    private Long id;
+
+    /**
+     * The owner of this attribute.
+     */
+    @ManyToOne(fetch = FetchType.EAGER)
+    private JPAConf owner;
+
+    /**
+     * The schema of this attribute.
+     */
+    @ManyToOne(fetch = FetchType.EAGER)
+    @JoinColumn(name = "schema_name")
+    private JPACPlainSchema schema;
+
+    /**
+     * Values of this attribute (if schema is not UNIQUE).
+     */
+    @OneToMany(cascade = CascadeType.MERGE, orphanRemoval = true, mappedBy = "attribute")
+    @Valid
+    private List<JPACPlainAttrValue> values;
+
+    /**
+     * Value of this attribute (if schema is UNIQUE).
+     */
+    @OneToOne(cascade = CascadeType.ALL, mappedBy = "attribute")
+    @Valid
+    private JPACPlainAttrUniqueValue uniqueValue;
+
+    /**
+     * Default constructor.
+     */
+    public JPACPlainAttr() {
+        super();
+        values = new ArrayList<>();
+    }
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public Conf getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final Attributable<?, ?, ?> owner) {
+        checkType(owner, JPAConf.class);
+        this.owner = (JPAConf) owner;
+    }
+
+    @Override
+    public CPlainSchema getSchema() {
+        return schema;
+    }
+
+    @Override
+    public void setSchema(final PlainSchema schema) {
+        checkType(schema, JPACPlainSchema.class);
+        this.schema = (JPACPlainSchema) schema;
+    }
+
+    @Override
+    protected boolean addValue(final PlainAttrValue attrValue) {
+        checkType(attrValue, JPACPlainAttrValue.class);
+        return values.add((JPACPlainAttrValue) attrValue);
+    }
+
+    @Override
+    public boolean removeValue(final PlainAttrValue attrValue) {
+        checkType(attrValue, JPACPlainAttrValue.class);
+        return values.remove((JPACPlainAttrValue) attrValue);
+    }
+
+    @Override
+    public List<? extends CPlainAttrValue> getValues() {
+        return values;
+    }
+
+    @Override
+    public CPlainAttrUniqueValue getUniqueValue() {
+        return uniqueValue;
+    }
+
+    @Override
+    public void setUniqueValue(final PlainAttrUniqueValue uniqueValue) {
+        checkType(owner, JPACPlainAttrUniqueValue.class);
+        this.uniqueValue = (JPACPlainAttrUniqueValue) uniqueValue;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPACPlainAttrUniqueValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPACPlainAttrUniqueValue.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPACPlainAttrUniqueValue.java
new file mode 100644
index 0000000..13e8e04
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPACPlainAttrUniqueValue.java
@@ -0,0 +1,78 @@
+/*
+ * 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.persistence.jpa.entity.conf;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.apache.syncope.persistence.api.entity.conf.CPlainAttr;
+import org.apache.syncope.persistence.api.entity.conf.CPlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.conf.CPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainAttrValue;
+
+@Entity
+@Table(name = JPACPlainAttrUniqueValue.TABLE)
+public class JPACPlainAttrUniqueValue extends AbstractPlainAttrValue implements CPlainAttrUniqueValue {
+
+    private static final long serialVersionUID = -64080804563305387L;
+
+    public static final String TABLE = "CPlainAttrUniqueValue";
+
+    @Id
+    private Long id;
+
+    @OneToOne(optional = false)
+    private JPACPlainAttr attribute;
+
+    @ManyToOne(optional = false)
+    @JoinColumn(name = "schema_name")
+    private JPACPlainSchema schema;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public CPlainAttr getAttr() {
+        return attribute;
+    }
+
+    @Override
+    public void setAttr(final PlainAttr attr) {
+        checkType(attr, JPACPlainAttr.class);
+        this.attribute = (JPACPlainAttr) attr;
+    }
+
+    @Override
+    public CPlainSchema getSchema() {
+        return schema;
+    }
+
+    @Override
+    public void setSchema(final PlainSchema schema) {
+        checkType(schema, JPACPlainSchema.class);
+        this.schema = (JPACPlainSchema) schema;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPACPlainAttrValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPACPlainAttrValue.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPACPlainAttrValue.java
new file mode 100644
index 0000000..70e30f3
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPACPlainAttrValue.java
@@ -0,0 +1,64 @@
+/*
+ * 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.persistence.jpa.entity.conf;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.conf.CPlainAttr;
+import org.apache.syncope.persistence.api.entity.conf.CPlainAttrValue;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainAttrValue;
+
+@Entity
+@Table(name = JPACPlainAttrValue.TABLE)
+@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
+public class JPACPlainAttrValue extends AbstractPlainAttrValue implements CPlainAttrValue {
+
+    private static final long serialVersionUID = -6259576015647897446L;
+
+    public static final String TABLE = "CPlainAttrValue";
+
+    @Id
+    private Long id;
+
+    @ManyToOne
+    @NotNull
+    private JPACPlainAttr attribute;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public CPlainAttr getAttr() {
+        return attribute;
+    }
+
+    @Override
+    public void setAttr(final PlainAttr attr) {
+        checkType(attr, JPACPlainAttr.class);
+        this.attribute = (JPACPlainAttr) attr;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPACPlainSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPACPlainSchema.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPACPlainSchema.java
new file mode 100644
index 0000000..e0c4ec8
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPACPlainSchema.java
@@ -0,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.persistence.jpa.entity.conf;
+
+import javax.persistence.Cacheable;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.conf.CPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainSchema;
+
+@Entity
+@Table(name = JPACPlainSchema.TABLE)
+@Cacheable
+public class JPACPlainSchema extends AbstractPlainSchema implements CPlainSchema {
+
+    private static final long serialVersionUID = 3363019039331594433L;
+
+    public static final String TABLE = "CPlainSchema";
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPAConf.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPAConf.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPAConf.java
new file mode 100644
index 0000000..3bfa884
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/conf/JPAConf.java
@@ -0,0 +1,116 @@
+/*
+ * 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.persistence.jpa.entity.conf;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.persistence.Cacheable;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.validation.Valid;
+import org.apache.syncope.persistence.api.entity.DerAttr;
+import org.apache.syncope.persistence.api.entity.VirAttr;
+import org.apache.syncope.persistence.api.entity.conf.CPlainAttr;
+import org.apache.syncope.persistence.api.entity.conf.Conf;
+import org.apache.syncope.persistence.jpa.entity.AbstractAttributable;
+
+@Entity
+@Table(name = JPAConf.TABLE)
+@Cacheable
+public class JPAConf extends AbstractAttributable<CPlainAttr, DerAttr, VirAttr> implements Conf {
+
+    private static final long serialVersionUID = -5281258853142421875L;
+
+    public static final String TABLE = "SyncopeConf";
+
+    @Id
+    private Long id;
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPACPlainAttr> plainAttrs;
+
+    public JPAConf() {
+        super();
+
+        plainAttrs = new ArrayList<>();
+    }
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public void setKey(final Long key) {
+        this.id = key;
+    }
+
+    @Override
+    public boolean addPlainAttr(final CPlainAttr attr) {
+        checkType(attr, JPACPlainAttr.class);
+        return plainAttrs.add((JPACPlainAttr) attr);
+    }
+
+    @Override
+    public boolean removePlainAttr(final CPlainAttr attr) {
+        checkType(attr, JPACPlainAttr.class);
+        return plainAttrs.remove((JPACPlainAttr) attr);
+    }
+
+    @Override
+    public List<? extends CPlainAttr> getPlainAttrs() {
+        return plainAttrs;
+    }
+
+    @Override
+    public boolean addDerAttr(final DerAttr attr) {
+        return false;
+    }
+
+    @Override
+    public boolean removeDerAttr(final DerAttr derAttr) {
+        return false;
+    }
+
+    @Override
+    public List<? extends DerAttr> getDerAttrs() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public boolean addVirAttr(final VirAttr attr) {
+        return false;
+    }
+
+    @Override
+    public boolean removeVirAttr(final VirAttr virAttr) {
+        return false;
+    }
+
+    @Override
+    public List<? extends VirAttr> getVirAttrs() {
+        return Collections.emptyList();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMDerAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMDerAttr.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMDerAttr.java
new file mode 100644
index 0000000..c154e90
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMDerAttr.java
@@ -0,0 +1,82 @@
+/*
+ * 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.persistence.jpa.entity.membership;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.Attributable;
+import org.apache.syncope.persistence.api.entity.DerSchema;
+import org.apache.syncope.persistence.api.entity.membership.MDerAttr;
+import org.apache.syncope.persistence.api.entity.membership.MDerAttrTemplate;
+import org.apache.syncope.persistence.api.entity.membership.MDerSchema;
+import org.apache.syncope.persistence.api.entity.membership.Membership;
+import org.apache.syncope.persistence.jpa.entity.AbstractDerAttr;
+
+@Entity
+@Table(name = JPAMDerAttr.TABLE)
+public class JPAMDerAttr extends AbstractDerAttr implements MDerAttr {
+
+    private static final long serialVersionUID = -443509121923448129L;
+
+    public static final String TABLE = "MDerAttr";
+
+    @ManyToOne
+    private JPAMembership owner;
+
+    @Column(nullable = false)
+    @OneToOne(cascade = CascadeType.MERGE)
+    private JPAMDerAttrTemplate template;
+
+    @Override
+    public Membership getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final Attributable<?, ?, ?> owner) {
+        checkType(owner, JPAMembership.class);
+        this.owner = (JPAMembership) owner;
+    }
+
+    @Override
+    public MDerAttrTemplate getTemplate() {
+        return template;
+    }
+
+    @Override
+    public void setTemplate(final MDerAttrTemplate template) {
+        checkType(template, JPAMDerAttrTemplate.class);
+        this.template = (JPAMDerAttrTemplate) template;
+    }
+
+    @Override
+    public MDerSchema getSchema() {
+        return template == null ? null : template.getSchema();
+    }
+
+    @Override
+    public void setSchema(final DerSchema schema) {
+        LOG.warn("This is role attribute, set template to select schema");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMDerAttrTemplate.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMDerAttrTemplate.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMDerAttrTemplate.java
new file mode 100644
index 0000000..7ec7fcf
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMDerAttrTemplate.java
@@ -0,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.persistence.jpa.entity.membership;
+
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.membership.MDerAttrTemplate;
+import org.apache.syncope.persistence.api.entity.membership.MDerSchema;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.jpa.entity.AbstractAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.role.JPARole;
+
+@Entity
+@Table(name = JPAMDerAttrTemplate.TABLE)
+public class JPAMDerAttrTemplate extends AbstractAttrTemplate<MDerSchema> implements MDerAttrTemplate {
+
+    private static final long serialVersionUID = -3424574558427502145L;
+
+    public static final String TABLE = "MDerAttrTemplate";
+
+    @ManyToOne
+    private JPARole owner;
+
+    @ManyToOne
+    @JoinColumn(name = "schema_name")
+    private JPAMDerSchema schema;
+
+    @Override
+    public MDerSchema getSchema() {
+        return schema;
+    }
+
+    @Override
+    public void setSchema(final MDerSchema schema) {
+        checkType(schema, JPAMDerSchema.class);
+        this.schema = (JPAMDerSchema) schema;
+    }
+
+    @Override
+    public Role getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final Role owner) {
+        checkType(owner, JPARole.class);
+        this.owner = (JPARole) owner;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMDerSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMDerSchema.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMDerSchema.java
new file mode 100644
index 0000000..d3e2e03
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMDerSchema.java
@@ -0,0 +1,34 @@
+/*
+ * 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.persistence.jpa.entity.membership;
+
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.membership.MDerSchema;
+import org.apache.syncope.persistence.jpa.entity.AbstractDerSchema;
+
+@Entity
+@Table(name = JPAMDerSchema.TABLE)
+public class JPAMDerSchema extends AbstractDerSchema implements MDerSchema {
+
+    private static final long serialVersionUID = -4694082505732174583L;
+
+    public static final String TABLE = "MDerSchema";
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainAttr.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainAttr.java
new file mode 100644
index 0000000..38f2b24
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainAttr.java
@@ -0,0 +1,141 @@
+/*
+ * 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.persistence.jpa.entity.membership;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.validation.Valid;
+import org.apache.syncope.persistence.api.entity.Attributable;
+import org.apache.syncope.persistence.api.entity.PlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttr;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttrTemplate;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttrValue;
+import org.apache.syncope.persistence.api.entity.membership.MPlainSchema;
+import org.apache.syncope.persistence.api.entity.membership.Membership;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainAttr;
+
+@Entity
+@Table(name = JPAMPlainAttr.TABLE)
+public class JPAMPlainAttr extends AbstractPlainAttr implements MPlainAttr {
+
+    private static final long serialVersionUID = 3755864809152866489L;
+
+    public static final String TABLE = "MPlainAttr";
+
+    @Id
+    private Long id;
+
+    @ManyToOne(fetch = FetchType.EAGER)
+    private JPAMembership owner;
+
+    @Column(nullable = false)
+    @OneToOne(cascade = CascadeType.MERGE)
+    private JPAMPlainAttrTemplate template;
+
+    @OneToMany(cascade = CascadeType.MERGE, orphanRemoval = true, mappedBy = "attribute")
+    @Valid
+    private List<JPAMPlainAttrValue> values;
+
+    @OneToOne(cascade = CascadeType.ALL, mappedBy = "attribute")
+    @Valid
+    private JPAMPlainAttrUniqueValue uniqueValue;
+
+    public JPAMPlainAttr() {
+        super();
+        values = new ArrayList<>();
+    }
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public Membership getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final Attributable<?, ?, ?> owner) {
+        checkType(owner, JPAMembership.class);
+        this.owner = (JPAMembership) owner;
+    }
+
+    @Override
+    public MPlainAttrTemplate getTemplate() {
+        return template;
+    }
+
+    @Override
+    public void setTemplate(final MPlainAttrTemplate template) {
+        checkType(template, JPAMPlainAttrTemplate.class);
+        this.template = (JPAMPlainAttrTemplate) template;
+    }
+
+    @Override
+    public MPlainSchema getSchema() {
+        return template == null ? null : template.getSchema();
+    }
+
+    @Override
+    public void setSchema(final PlainSchema schema) {
+        LOG.warn("This is role attribute, set template to select schema");
+    }
+
+    @Override
+    protected boolean addValue(final PlainAttrValue attrValue) {
+        checkType(attrValue, JPAMPlainAttrValue.class);
+        return values.add((JPAMPlainAttrValue) attrValue);
+    }
+
+    @Override
+    public boolean removeValue(final PlainAttrValue attrValue) {
+        checkType(attrValue, JPAMPlainAttrValue.class);
+        return values.remove((JPAMPlainAttrValue) attrValue);
+    }
+
+    @Override
+    public List<? extends MPlainAttrValue> getValues() {
+        return values;
+    }
+
+    @Override
+    public MPlainAttrUniqueValue getUniqueValue() {
+        return uniqueValue;
+    }
+
+    @Override
+    public void setUniqueValue(final PlainAttrUniqueValue uniqueValue) {
+        checkType(owner, JPAMPlainAttrUniqueValue.class);
+        this.uniqueValue = (JPAMPlainAttrUniqueValue) uniqueValue;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainAttrTemplate.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainAttrTemplate.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainAttrTemplate.java
new file mode 100644
index 0000000..fb8e728
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainAttrTemplate.java
@@ -0,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.persistence.jpa.entity.membership;
+
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttrTemplate;
+import org.apache.syncope.persistence.api.entity.membership.MPlainSchema;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.jpa.entity.AbstractAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.role.JPARole;
+
+@Entity
+@Table(name = JPAMPlainAttrTemplate.TABLE)
+public class JPAMPlainAttrTemplate extends AbstractAttrTemplate<MPlainSchema> implements MPlainAttrTemplate {
+
+    private static final long serialVersionUID = -3424574558427502145L;
+
+    public static final String TABLE = "MPlainAttrTemplate";
+
+    @ManyToOne
+    private JPARole owner;
+
+    @ManyToOne
+    @JoinColumn(name = "schema_name")
+    private JPAMPlainSchema schema;
+
+    @Override
+    public MPlainSchema getSchema() {
+        return schema;
+    }
+
+    @Override
+    public void setSchema(final MPlainSchema schema) {
+        checkType(schema, JPAMPlainSchema.class);
+        this.schema = (JPAMPlainSchema) schema;
+    }
+
+    @Override
+    public JPARole getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final Role owner) {
+        checkType(owner, JPARole.class);
+        this.owner = (JPARole) owner;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainAttrUniqueValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainAttrUniqueValue.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainAttrUniqueValue.java
new file mode 100644
index 0000000..344ebc2
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainAttrUniqueValue.java
@@ -0,0 +1,78 @@
+/*
+ * 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.persistence.jpa.entity.membership;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttr;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttrUniqueValue;
+import org.apache.syncope.persistence.api.entity.membership.MPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainAttrValue;
+
+@Entity
+@Table(name = JPAMPlainAttrUniqueValue.TABLE)
+public class JPAMPlainAttrUniqueValue extends AbstractPlainAttrValue implements MPlainAttrUniqueValue {
+
+    private static final long serialVersionUID = 3985867531873453718L;
+
+    public static final String TABLE = "MPlainAttrUniqueValue";
+
+    @Id
+    private Long id;
+
+    @OneToOne(optional = false)
+    private JPAMPlainAttr attribute;
+
+    @ManyToOne(optional = false)
+    @JoinColumn(name = "schema_name")
+    private JPAMPlainSchema schema;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public MPlainAttr getAttr() {
+        return attribute;
+    }
+
+    @Override
+    public void setAttr(final PlainAttr attr) {
+        checkType(attr, JPAMPlainAttr.class);
+        this.attribute = (JPAMPlainAttr) attr;
+    }
+
+    @Override
+    public MPlainSchema getSchema() {
+        return schema;
+    }
+
+    @Override
+    public void setSchema(final PlainSchema schema) {
+        checkType(schema, JPAMPlainSchema.class);
+        this.schema = (JPAMPlainSchema) schema;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainAttrValue.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainAttrValue.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainAttrValue.java
new file mode 100644
index 0000000..520e244
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainAttrValue.java
@@ -0,0 +1,64 @@
+/*
+ * 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.persistence.jpa.entity.membership;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+import org.apache.syncope.persistence.api.entity.PlainAttr;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttr;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttrValue;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainAttrValue;
+
+@Entity
+@Table(name = JPAMPlainAttrValue.TABLE)
+@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
+public class JPAMPlainAttrValue extends AbstractPlainAttrValue implements MPlainAttrValue {
+
+    private static final long serialVersionUID = -7188881172631198385L;
+
+    public static final String TABLE = "MPlainAttrValue";
+
+    @Id
+    private Long id;
+
+    @ManyToOne
+    @NotNull
+    private JPAMPlainAttr attribute;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public MPlainAttr getAttr() {
+        return attribute;
+    }
+
+    @Override
+    public void setAttr(final PlainAttr attr) {
+        checkType(attr, JPAMPlainAttr.class);
+        this.attribute = (JPAMPlainAttr) attr;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainSchema.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainSchema.java
new file mode 100644
index 0000000..e4ba2a9
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMPlainSchema.java
@@ -0,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.persistence.jpa.entity.membership;
+
+import javax.persistence.Cacheable;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.membership.MPlainSchema;
+import org.apache.syncope.persistence.jpa.entity.AbstractPlainSchema;
+
+@Entity
+@Table(name = JPAMPlainSchema.TABLE)
+@Cacheable
+public class JPAMPlainSchema extends AbstractPlainSchema implements MPlainSchema {
+
+    private static final long serialVersionUID = -8053736450044590651L;
+
+    public static final String TABLE = "MPlainSchema";
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMVirAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMVirAttr.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMVirAttr.java
new file mode 100644
index 0000000..4cfe207
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMVirAttr.java
@@ -0,0 +1,81 @@
+/*
+ * 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.persistence.jpa.entity.membership;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.Attributable;
+import org.apache.syncope.persistence.api.entity.VirSchema;
+import org.apache.syncope.persistence.api.entity.membership.MVirAttr;
+import org.apache.syncope.persistence.api.entity.membership.MVirAttrTemplate;
+import org.apache.syncope.persistence.api.entity.membership.MVirSchema;
+import org.apache.syncope.persistence.api.entity.membership.Membership;
+import org.apache.syncope.persistence.jpa.entity.AbstractVirAttr;
+
+@Entity
+@Table(name = JPAMVirAttr.TABLE)
+public class JPAMVirAttr extends AbstractVirAttr implements MVirAttr {
+
+    private static final long serialVersionUID = 7774760571251641332L;
+
+    public static final String TABLE = "MVirAttr";
+
+    @ManyToOne
+    private JPAMembership owner;
+
+    @Column(nullable = false)
+    @OneToOne(cascade = CascadeType.MERGE)
+    private JPAMVirAttrTemplate template;
+
+    @Override
+    public Membership getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final Attributable<?, ?, ?> owner) {
+        checkType(owner, JPAMembership.class);
+        this.owner = (JPAMembership) owner;
+    }
+
+    @Override
+    public MVirAttrTemplate getTemplate() {
+        return template;
+    }
+
+    @Override
+    public void setTemplate(final MVirAttrTemplate template) {
+        checkType(template, JPAMVirAttrTemplate.class);
+        this.template = (JPAMVirAttrTemplate) template;
+    }
+
+    @Override
+    public MVirSchema getSchema() {
+        return template == null ? null : template.getSchema();
+    }
+
+    @Override
+    public void setSchema(final VirSchema schema) {
+        LOG.warn("This is role attribute, set template to select schema");
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMVirAttrTemplate.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMVirAttrTemplate.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMVirAttrTemplate.java
new file mode 100644
index 0000000..7bd60db
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMVirAttrTemplate.java
@@ -0,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.persistence.jpa.entity.membership;
+
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.membership.MVirAttrTemplate;
+import org.apache.syncope.persistence.api.entity.membership.MVirSchema;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.jpa.entity.AbstractAttrTemplate;
+import org.apache.syncope.persistence.jpa.entity.role.JPARole;
+
+@Entity
+@Table(name = JPAMVirAttrTemplate.TABLE)
+public class JPAMVirAttrTemplate extends AbstractAttrTemplate<MVirSchema> implements MVirAttrTemplate {
+
+    private static final long serialVersionUID = -3424574558427502145L;
+
+    public static final String TABLE = "MVirAttrTemplate";
+
+    @ManyToOne
+    private JPARole owner;
+
+    @ManyToOne
+    @JoinColumn(name = "schema_name")
+    private JPAMVirSchema schema;
+
+    @Override
+    public MVirSchema getSchema() {
+        return schema;
+    }
+
+    @Override
+    public void setSchema(final MVirSchema schema) {
+        checkType(schema, JPAMVirSchema.class);
+        this.schema = (JPAMVirSchema) schema;
+    }
+
+    @Override
+    public Role getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final Role role) {
+        checkType(role, JPARole.class);
+        this.owner = (JPARole) role;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMVirSchema.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMVirSchema.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMVirSchema.java
new file mode 100644
index 0000000..78b0358
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMVirSchema.java
@@ -0,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.persistence.jpa.entity.membership;
+
+import javax.persistence.Cacheable;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.membership.MVirSchema;
+import org.apache.syncope.persistence.jpa.entity.AbstractVirSchema;
+
+@Entity
+@Table(name = JPAMVirSchema.TABLE)
+@Cacheable
+public class JPAMVirSchema extends AbstractVirSchema implements MVirSchema {
+
+    private static final long serialVersionUID = 6255905733563668766L;
+
+    public static final String TABLE = "MVirSchema";
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMembership.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMembership.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMembership.java
new file mode 100644
index 0000000..5f7cef3
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/membership/JPAMembership.java
@@ -0,0 +1,195 @@
+/*
+ * 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.persistence.jpa.entity.membership;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+import javax.validation.Valid;
+import org.apache.syncope.persistence.api.entity.membership.MDerAttr;
+import org.apache.syncope.persistence.api.entity.membership.MDerAttrTemplate;
+import org.apache.syncope.persistence.api.entity.membership.MPlainAttr;
+import org.apache.syncope.persistence.api.entity.membership.MVirAttr;
+import org.apache.syncope.persistence.api.entity.membership.MVirAttrTemplate;
+import org.apache.syncope.persistence.api.entity.membership.Membership;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.persistence.jpa.entity.AbstractAttributable;
+import org.apache.syncope.persistence.jpa.entity.role.JPARole;
+import org.apache.syncope.persistence.jpa.entity.user.JPAUser;
+
+@Entity
+@Table(name = JPAMembership.TABLE, uniqueConstraints =
+        @UniqueConstraint(columnNames = { "user_id", "role_id" }))
+public class JPAMembership extends AbstractAttributable<MPlainAttr, MDerAttr, MVirAttr> implements Membership {
+
+    private static final long serialVersionUID = 5030106264797289469L;
+
+    public static final String TABLE = "Membership";
+
+    @Id
+    private Long id;
+
+    @ManyToOne
+    private JPAUser user;
+
+    @ManyToOne
+    private JPARole role;
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPAMPlainAttr> plainAttrs;
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPAMDerAttr> derAttrs;
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPAMVirAttr> virAttrs;
+
+    public JPAMembership() {
+        super();
+
+        plainAttrs = new ArrayList<>();
+        derAttrs = new ArrayList<>();
+        virAttrs = new ArrayList<>();
+    }
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public Role getRole() {
+        return role;
+    }
+
+    @Override
+    public void setRole(final Role role) {
+        checkType(role, JPARole.class);
+        this.role = (JPARole) role;
+    }
+
+    @Override
+    public User getUser() {
+        return user;
+    }
+
+    @Override
+    public void setUser(final User user) {
+        checkType(user, JPAUser.class);
+        this.user = (JPAUser) user;
+    }
+
+    @Override
+    public boolean addPlainAttr(final MPlainAttr attr) {
+        checkType(attr, JPAMPlainAttr.class);
+        return plainAttrs.add((JPAMPlainAttr) attr);
+    }
+
+    @Override
+    public boolean removePlainAttr(final MPlainAttr attr) {
+        checkType(attr, JPAMPlainAttr.class);
+        return plainAttrs.remove((JPAMPlainAttr) attr);
+    }
+
+    @Override
+    public List<? extends MPlainAttr> getPlainAttrs() {
+        return plainAttrs;
+    }
+
+    @Override
+    public boolean addDerAttr(final MDerAttr derAttr) {
+        checkType(derAttr, JPAMDerAttr.class);
+
+        if (getRole() != null && derAttr.getSchema() != null) {
+            MDerAttrTemplate found = null;
+            for (MDerAttrTemplate template : getRole().findInheritedTemplates(MDerAttrTemplate.class)) {
+                if (derAttr.getSchema().equals(template.getSchema())) {
+                    found = template;
+                }
+            }
+            if (found != null) {
+                derAttr.setTemplate(found);
+                return derAttrs.add((JPAMDerAttr) derAttr);
+            }
+        }
+
+        LOG.warn("Attribute not added because either role was not yet set, "
+                + "schema was not specified or no template for that schema is available");
+        return false;
+    }
+
+    @Override
+    public boolean removeDerAttr(final MDerAttr derAttr) {
+        checkType(derAttr, JPAMDerAttr.class);
+        return derAttrs.remove((JPAMDerAttr) derAttr);
+    }
+
+    @Override
+    public List<? extends MDerAttr> getDerAttrs() {
+        return derAttrs;
+    }
+
+    @Override
+    public boolean addVirAttr(final MVirAttr virAttr) {
+        checkType(virAttr, JPAMVirAttr.class);
+
+        if (getRole() != null && virAttr.getSchema() != null) {
+            MVirAttrTemplate found = null;
+            for (MVirAttrTemplate template : getRole().findInheritedTemplates(MVirAttrTemplate.class)) {
+                if (virAttr.getSchema().equals(template.getSchema())) {
+                    found = template;
+                }
+            }
+            if (found != null) {
+                virAttr.setTemplate(found);
+                return virAttrs.add((JPAMVirAttr) virAttr);
+            }
+        }
+
+        LOG.warn("Attribute not added because either "
+                + "schema was not specified or no template for that schema is available");
+        return false;
+    }
+
+    @Override
+    public boolean removeVirAttr(final MVirAttr virAttr) {
+        checkType(virAttr, JPAMVirAttr.class);
+        return virAttrs.remove((JPAMVirAttr) virAttr);
+    }
+
+    @Override
+    public List<? extends MVirAttr> getVirAttrs() {
+        return virAttrs;
+    }
+
+    @Override
+    public String toString() {
+        return "Membership[" + "id=" + id + ", " + user + ", " + role + ']';
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARDerAttr.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARDerAttr.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARDerAttr.java
new file mode 100644
index 0000000..a4dbd7a
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARDerAttr.java
@@ -0,0 +1,82 @@
+/*
+ * 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.persistence.jpa.entity.role;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.Attributable;
+import org.apache.syncope.persistence.api.entity.DerSchema;
+import org.apache.syncope.persistence.api.entity.role.RDerAttr;
+import org.apache.syncope.persistence.api.entity.role.RDerAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.RDerSchema;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.jpa.entity.AbstractDerAttr;
+
+@Entity
+@Table(name = JPARDerAttr.TABLE)
+public class JPARDerAttr extends AbstractDerAttr implements RDerAttr {
+
+    private static final long serialVersionUID = 8007080005675899946L;
+
+    public static final String TABLE = "RDerAttr";
+
+    @ManyToOne
+    private JPARole owner;
+
+    @Column(nullable = false)
+    @OneToOne(cascade = CascadeType.MERGE)
+    private JPARDerAttrTemplate template;
+
+    @Override
+    public Role getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final Attributable<?, ?, ?> owner) {
+        checkType(owner, JPARole.class);
+        this.owner = (JPARole) owner;
+    }
+
+    @Override
+    public RDerAttrTemplate getTemplate() {
+        return template;
+    }
+
+    @Override
+    public void setTemplate(final RDerAttrTemplate template) {
+        checkType(template, JPARDerAttrTemplate.class);
+        this.template = (JPARDerAttrTemplate) template;
+    }
+
+    @Override
+    public RDerSchema getSchema() {
+        return template == null ? null : template.getSchema();
+    }
+
+    @Override
+    public void setSchema(final DerSchema schema) {
+        LOG.warn("This is role attribute, set template to select schema");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/556d5186/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARDerAttrTemplate.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARDerAttrTemplate.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARDerAttrTemplate.java
new file mode 100644
index 0000000..ba565a7
--- /dev/null
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/entity/role/JPARDerAttrTemplate.java
@@ -0,0 +1,66 @@
+/*
+ * 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.persistence.jpa.entity.role;
+
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.apache.syncope.persistence.api.entity.role.RDerAttrTemplate;
+import org.apache.syncope.persistence.api.entity.role.RDerSchema;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.jpa.entity.AbstractAttrTemplate;
+
+@Entity
+@Table(name = JPARDerAttrTemplate.TABLE)
+public class JPARDerAttrTemplate extends AbstractAttrTemplate<RDerSchema> implements RDerAttrTemplate {
+
+    private static final long serialVersionUID = -3424574558427502145L;
+
+    public static final String TABLE = "RDerAttrTemplate";
+
+    @ManyToOne
+    private JPARole owner;
+
+    @ManyToOne
+    @JoinColumn(name = "schema_name")
+    private JPARDerSchema schema;
+
+    @Override
+    public RDerSchema getSchema() {
+        return schema;
+    }
+
+    @Override
+    public void setSchema(final RDerSchema schema) {
+        checkType(schema, JPARDerSchema.class);
+        this.schema = (JPARDerSchema) schema;
+    }
+
+    @Override
+    public Role getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final Role owner) {
+        checkType(owner, JPARole.class);
+        this.owner = (JPARole) owner;
+    }
+}