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:12:11 UTC

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

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;
+    }
+}