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/02/05 17:00:38 UTC

[07/52] syncope git commit: [SYNCOPE-620] Console (JAR) in, now time for console-reference

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/fit/server-reference/src/main/webapp/db.jsp
----------------------------------------------------------------------
diff --git a/syncope620/fit/server-reference/src/main/webapp/db.jsp b/syncope620/fit/server-reference/src/main/webapp/db.jsp
new file mode 100644
index 0000000..2a4c6ac
--- /dev/null
+++ b/syncope620/fit/server-reference/src/main/webapp/db.jsp
@@ -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.
+--%>
+<%@page import="java.sql.SQLException"%>
+<%@page import="org.h2.tools.Server"%>
+<%@page contentType="text/html" pageEncoding="UTF-8"%>
+<%
+    Server h2Datastore = (Server) getServletConfig().getServletContext().getAttribute("H2_DATASTORE");
+    if (h2Datastore == null || !h2Datastore.isRunning(true)) {
+        try {
+            h2Datastore = Server.createWebServer("-webPort", "8082");
+            h2Datastore.start();
+
+            getServletConfig().getServletContext().setAttribute("H2_DATASTORE", h2Datastore);
+        } catch (SQLException e) {
+            getServletConfig().getServletContext().log("Could not start H2 web console (datastore)", e);
+        }
+
+        response.sendRedirect("http://localhost:8082");
+    }
+%>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/AbstractITCase.java
----------------------------------------------------------------------
diff --git a/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/AbstractITCase.java b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/AbstractITCase.java
new file mode 100644
index 0000000..cf545a7
--- /dev/null
+++ b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/AbstractITCase.java
@@ -0,0 +1,388 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.fit.server.reference;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+import java.util.UUID;
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.directory.InitialDirContext;
+import javax.sql.DataSource;
+import javax.ws.rs.core.Response;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.lib.mod.AttrMod;
+import org.apache.syncope.common.lib.mod.RoleMod;
+import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.common.lib.to.AbstractPolicyTO;
+import org.apache.syncope.common.lib.to.AbstractSchemaTO;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.ConnConfProperty;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.CamelRouteService;
+import org.apache.syncope.common.rest.api.service.ConfigurationService;
+import org.apache.syncope.common.rest.api.service.ConnectorService;
+import org.apache.syncope.common.rest.api.service.EntitlementService;
+import org.apache.syncope.common.rest.api.service.LoggerService;
+import org.apache.syncope.common.rest.api.service.NotificationService;
+import org.apache.syncope.common.rest.api.service.PolicyService;
+import org.apache.syncope.common.rest.api.service.ReportService;
+import org.apache.syncope.common.rest.api.service.ResourceService;
+import org.apache.syncope.common.rest.api.service.RoleService;
+import org.apache.syncope.common.rest.api.service.SchemaService;
+import org.apache.syncope.common.rest.api.service.SecurityQuestionService;
+import org.apache.syncope.common.rest.api.service.SyncopeService;
+import org.apache.syncope.common.rest.api.service.TaskService;
+import org.apache.syncope.common.rest.api.service.UserSelfService;
+import org.apache.syncope.common.rest.api.service.UserService;
+import org.apache.syncope.common.rest.api.service.UserWorkflowService;
+import org.apache.syncope.common.rest.api.service.WorkflowService;
+import org.identityconnectors.common.security.Encryptor;
+import org.junit.BeforeClass;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { "classpath:testJDBCContext.xml" })
+public abstract class AbstractITCase {
+
+    /**
+     * Logger.
+     */
+    protected static final Logger LOG = LoggerFactory.getLogger(AbstractITCase.class);
+
+    protected static final String ADMIN_UNAME = "admin";
+
+    protected static final String ADMIN_PWD = "password";
+
+    private static final String ADDRESS = "http://localhost:9080/syncope/rest";
+
+    private static final String ENV_KEY_CONTENT_TYPE = "jaxrsContentType";
+
+    protected static final SyncopeClientFactoryBean clientFactory = new SyncopeClientFactoryBean().setAddress(ADDRESS);
+
+    protected static final String RESOURCE_NAME_WS1 = "ws-target-resource-1";
+
+    protected static final String RESOURCE_NAME_WS2 = "ws-target-resource-2";
+
+    protected static final String RESOURCE_NAME_LDAP = "resource-ldap";
+
+    protected static final String RESOURCE_NAME_TESTDB = "resource-testdb";
+
+    protected static final String RESOURCE_NAME_TESTDB2 = "resource-testdb2";
+
+    protected static final String RESOURCE_NAME_CSV = "resource-csv";
+
+    protected static final String RESOURCE_NAME_DBSYNC = "resource-db-sync";
+
+    protected static final String RESOURCE_NAME_DBVIRATTR = "resource-db-virattr";
+
+    protected static final String RESOURCE_NAME_NOPROPAGATION = "ws-target-resource-nopropagation";
+
+    protected static final String RESOURCE_NAME_NOPROPAGATION2 = "ws-target-resource-nopropagation2";
+
+    protected static final String RESOURCE_NAME_NOPROPAGATION3 = "ws-target-resource-nopropagation3";
+
+    protected static final String RESOURCE_NAME_NOPROPAGATION4 = "ws-target-resource-nopropagation4";
+
+    protected static final String RESOURCE_NAME_RESETSYNCTOKEN = "ws-target-resource-update-resetsynctoken";
+
+    protected static final String RESOURCE_NAME_TIMEOUT = "ws-target-resource-timeout";
+
+    protected static final String RESOURCE_NAME_MAPPINGS1 = "ws-target-resource-list-mappings-1";
+
+    protected static final String RESOURCE_NAME_MAPPINGS2 = "ws-target-resource-list-mappings-2";
+
+    protected static final String RESOURCE_NAME_CREATE = "ws-target-resource-create";
+
+    protected static final String RESOURCE_NAME_CREATE_SINGLE = "ws-target-resource-create-single";
+
+    protected static final String RESOURCE_NAME_CREATE_WRONG = "ws-target-resource-create-wrong";
+
+    protected static final String RESOURCE_NAME_DELETE = "ws-target-resource-delete";
+
+    protected static final String RESOURCE_NAME_UPDATE = "ws-target-resource-update";
+
+    protected static final String RESOURCE_NAME_CREATE_NONE = "ws-target-resource-create-none";
+
+    protected static String ANONYMOUS_UNAME;
+
+    protected static String ANONYMOUS_KEY;
+
+    protected static SyncopeClient adminClient;
+
+    protected static SyncopeService syncopeService;
+
+    protected static UserService userService;
+
+    protected static UserSelfService userSelfService;
+
+    protected static UserWorkflowService userWorkflowService;
+
+    protected static RoleService roleService;
+
+    protected static ResourceService resourceService;
+
+    protected static EntitlementService entitlementService;
+
+    protected static ConfigurationService configurationService;
+
+    protected static ConnectorService connectorService;
+
+    protected static LoggerService loggerService;
+
+    protected static ReportService reportService;
+
+    protected static TaskService taskService;
+
+    protected static WorkflowService workflowService;
+
+    protected static NotificationService notificationService;
+
+    protected static SchemaService schemaService;
+
+    protected static PolicyService policyService;
+
+    protected static SecurityQuestionService securityQuestionService;
+    
+    protected static CamelRouteService camelRouteService;
+
+    @Autowired
+    protected DataSource testDataSource;
+
+    @BeforeClass
+    public static void securitySetup() {
+        InputStream propStream = null;
+        try {
+            propStream = Encryptor.class.getResourceAsStream("/security.properties");
+            Properties props = new Properties();
+            props.load(propStream);
+
+            ANONYMOUS_UNAME = props.getProperty("anonymousUser");
+            ANONYMOUS_KEY = props.getProperty("anonymousKey");
+        } catch (Exception e) {
+            LOG.error("Could not read secretKey", e);
+        } finally {
+            IOUtils.closeQuietly(propStream);
+        }
+
+        assertNotNull(ANONYMOUS_UNAME);
+        assertNotNull(ANONYMOUS_KEY);
+    }
+
+    @BeforeClass
+    public static void restSetup() {
+        final String envContentType = System.getProperty(ENV_KEY_CONTENT_TYPE);
+        if (StringUtils.isNotBlank(envContentType)) {
+            clientFactory.setContentType(envContentType);
+        }
+        LOG.info("Performing IT with content type {}", clientFactory.getContentType().getMediaType());
+
+        adminClient = clientFactory.create(ADMIN_UNAME, ADMIN_PWD);
+
+        syncopeService = adminClient.getService(SyncopeService.class);
+        userService = adminClient.getService(UserService.class);
+        userSelfService = adminClient.getService(UserSelfService.class);
+        userWorkflowService = adminClient.getService(UserWorkflowService.class);
+        roleService = adminClient.getService(RoleService.class);
+        resourceService = adminClient.getService(ResourceService.class);
+        entitlementService = adminClient.getService(EntitlementService.class);
+        configurationService = adminClient.getService(ConfigurationService.class);
+        connectorService = adminClient.getService(ConnectorService.class);
+        loggerService = adminClient.getService(LoggerService.class);
+        reportService = adminClient.getService(ReportService.class);
+        taskService = adminClient.getService(TaskService.class);
+        policyService = adminClient.getService(PolicyService.class);
+        workflowService = adminClient.getService(WorkflowService.class);
+        notificationService = adminClient.getService(NotificationService.class);
+        schemaService = adminClient.getService(SchemaService.class);
+        securityQuestionService = adminClient.getService(SecurityQuestionService.class);
+        camelRouteService = adminClient.getService(CamelRouteService.class);
+    }
+
+    protected static String getUUIDString() {
+        return UUID.randomUUID().toString().substring(0, 8);
+    }
+
+    protected static AttrTO attrTO(final String schema, final String value) {
+        AttrTO attr = new AttrTO();
+        attr.setSchema(schema);
+        attr.getValues().add(value);
+        return attr;
+    }
+
+    protected static AttrMod attrMod(final String schema, final String valueToBeAdded) {
+        AttrMod attr = new AttrMod();
+        attr.setSchema(schema);
+        attr.getValuesToBeAdded().add(valueToBeAdded);
+        return attr;
+    }
+
+    protected UserTO createUser(final UserTO userTO) {
+        return createUser(userTO, true);
+    }
+
+    protected UserTO createUser(final UserTO userTO, final boolean storePassword) {
+        Response response = userService.create(userTO, storePassword);
+        if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) {
+            Exception ex = clientFactory.getExceptionMapper().fromResponse(response);
+            if (ex != null) {
+                throw (RuntimeException) ex;
+            }
+        }
+        return response.readEntity(UserTO.class);
+    }
+
+    protected UserTO readUser(final String username) {
+        return userService.read(Long.valueOf(
+                userService.getUserId(username).getHeaderString(RESTHeaders.USER_ID)));
+    }
+
+    protected UserTO updateUser(final UserMod userMod) {
+        return userService.update(userMod.getKey(), userMod).readEntity(UserTO.class);
+    }
+
+    protected UserTO deleteUser(final Long id) {
+        return userService.delete(id).readEntity(UserTO.class);
+    }
+
+    public <T> T getObject(final URI location, final Class<?> serviceClass, final Class<T> resultClass) {
+        WebClient webClient = WebClient.fromClient(WebClient.client(adminClient.getService(serviceClass)));
+        webClient.accept(clientFactory.getContentType().getMediaType()).to(location.toASCIIString(), false);
+
+        return webClient.get(resultClass);
+    }
+
+    @SuppressWarnings("unchecked")
+    protected <T extends AbstractSchemaTO> T createSchema(final AttributableType kind,
+            final SchemaType type, final T schemaTO) {
+
+        Response response = schemaService.create(kind, type, schemaTO);
+        if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) {
+            Exception ex = clientFactory.getExceptionMapper().fromResponse(response);
+            if (ex != null) {
+                throw (RuntimeException) ex;
+            }
+        }
+
+        return (T) getObject(response.getLocation(), SchemaService.class, schemaTO.getClass());
+    }
+
+    protected RoleTO createRole(final RoleTO newRoleTO) {
+        Response response = roleService.create(newRoleTO);
+        if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) {
+            Exception ex = clientFactory.getExceptionMapper().fromResponse(response);
+            if (ex != null) {
+                throw (RuntimeException) ex;
+            }
+        }
+        return getObject(response.getLocation(), RoleService.class, RoleTO.class);
+    }
+
+    protected RoleTO updateRole(final RoleMod roleMod) {
+        return roleService.update(roleMod.getKey(), roleMod).readEntity(RoleTO.class);
+    }
+
+    protected RoleTO deleteRole(final Long id) {
+        return roleService.delete(id).readEntity(RoleTO.class);
+    }
+
+    @SuppressWarnings("unchecked")
+    protected <T extends AbstractPolicyTO> T createPolicy(final T policy) {
+        Response response = policyService.create(policy);
+        if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) {
+            Exception ex = clientFactory.getExceptionMapper().fromResponse(response);
+            if (ex != null) {
+                throw (RuntimeException) ex;
+            }
+        }
+        return (T) getObject(response.getLocation(), PolicyService.class, policy.getClass());
+    }
+
+    protected ResourceTO createResource(final ResourceTO resourceTO) {
+        Response response = resourceService.create(resourceTO);
+        if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) {
+            Exception ex = clientFactory.getExceptionMapper().fromResponse(response);
+            if (ex != null) {
+                throw (RuntimeException) ex;
+            }
+        }
+        return getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes", "UseOfObsoleteCollectionType" })
+    protected InitialDirContext getLdapResourceDirContext(final String bindDn, final String bindPwd)
+            throws NamingException {
+        ResourceTO ldapRes = resourceService.read(RESOURCE_NAME_LDAP);
+        final Map<String, ConnConfProperty> ldapConnConf =
+                connectorService.read(ldapRes.getConnectorId()).getConfigurationMap();
+
+        Hashtable env = new Hashtable();
+        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
+        env.put(Context.PROVIDER_URL, "ldap://" + ldapConnConf.get("host").getValues().get(0)
+                + ":" + ldapConnConf.get("port").getValues().get(0) + "/");
+        env.put(Context.SECURITY_AUTHENTICATION, "simple");
+        env.put(Context.SECURITY_PRINCIPAL,
+                bindDn == null ? ldapConnConf.get("principal").getValues().get(0) : bindDn);
+        env.put(Context.SECURITY_CREDENTIALS,
+                bindPwd == null ? ldapConnConf.get("credentials").getValues().get(0) : bindPwd);
+
+        return new InitialDirContext(env);
+    }
+
+    protected Object getLdapRemoteObject(final String bindDn, final String bindPwd, final String objectDn) {
+        InitialDirContext ctx = null;
+        try {
+            ctx = getLdapResourceDirContext(bindDn, bindPwd);
+            return ctx.lookup(objectDn);
+        } catch (Exception e) {
+            return null;
+        } finally {
+            if (ctx != null) {
+                try {
+                    ctx.close();
+                } catch (NamingException e) {
+                    // ignore
+                }
+            }
+        }
+    }
+
+    protected Object getLdapRemoteObject(final String objectDn) {
+        return getLdapRemoteObject(null, null, objectDn);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/AbstractTaskITCase.java
----------------------------------------------------------------------
diff --git a/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/AbstractTaskITCase.java b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/AbstractTaskITCase.java
new file mode 100644
index 0000000..afc9752
--- /dev/null
+++ b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/AbstractTaskITCase.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.fit.server.reference;
+
+import static org.apache.syncope.fit.server.reference.AbstractITCase.taskService;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.TaskExecTO;
+import org.apache.syncope.common.lib.to.UserTO;
+
+public abstract class AbstractTaskITCase extends AbstractITCase {
+
+    protected static final Long SYNC_TASK_ID = 4L;
+
+    protected static final Long SCHED_TASK_ID = 5L;
+
+    protected static class ThreadExec implements Callable<TaskExecTO> {
+
+        private final AbstractTaskITCase test;
+
+        private final Long taskKey;
+
+        private final int maxWaitSeconds;
+
+        private final boolean dryRun;
+
+        public ThreadExec(AbstractTaskITCase test, Long taskKey, int maxWaitSeconds, boolean dryRun) {
+            this.test = test;
+            this.taskKey = taskKey;
+            this.maxWaitSeconds = maxWaitSeconds;
+            this.dryRun = dryRun;
+        }
+
+        @Override
+        public TaskExecTO call() throws Exception {
+            return test.execSyncTask(taskKey, maxWaitSeconds, dryRun);
+        }
+    }
+
+    /**
+     * Remove initial and synchronized users to make test re-runnable.
+     */
+    protected void removeTestUsers() {
+        for (int i = 0; i < 10; i++) {
+            String cUserName = "test" + i;
+            try {
+                UserTO cUserTO = readUser(cUserName);
+                userService.delete(cUserTO.getKey());
+            } catch (Exception e) {
+                // Ignore
+            }
+        }
+    }
+
+    protected TaskExecTO execSyncTask(final Long taskKey, final int maxWaitSeconds, final boolean dryRun) {
+        AbstractTaskTO taskTO = taskService.read(taskKey);
+        assertNotNull(taskTO);
+        assertNotNull(taskTO.getExecutions());
+
+        int preSyncSize = taskTO.getExecutions().size();
+        TaskExecTO execution = taskService.execute(taskTO.getKey(), dryRun);
+        assertEquals("JOB_FIRED", execution.getStatus());
+
+        int i = 0;
+        int maxit = maxWaitSeconds;
+
+        // wait for sync completion (executions incremented)
+        do {
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+            }
+
+            taskTO = taskService.read(taskTO.getKey());
+
+            assertNotNull(taskTO);
+            assertNotNull(taskTO.getExecutions());
+
+            i++;
+        } while (preSyncSize == taskTO.getExecutions().size() && i < maxit);
+        if (i == maxit) {
+            fail("Timeout when executing task " + taskKey);
+        }
+        return taskTO.getExecutions().get(taskTO.getExecutions().size() - 1);
+    }
+
+    protected Map<Long, TaskExecTO> execSyncTasks(
+            final Set<Long> taskKeys, final int maxWaitSeconds, final boolean dryRun) throws Exception {
+
+        final ExecutorService service = Executors.newFixedThreadPool(taskKeys.size());
+        final List<Future<TaskExecTO>> futures = new ArrayList<>();
+
+        for (Long key : taskKeys) {
+            futures.add(service.submit(new ThreadExec(this, key, maxWaitSeconds, dryRun)));
+        }
+
+        final Map<Long, TaskExecTO> res = new HashMap<>();
+
+        for (Future<TaskExecTO> future : futures) {
+            TaskExecTO taskExecTO = future.get(100, TimeUnit.SECONDS);
+            res.put(taskExecTO.getTask(), taskExecTO);
+        }
+
+        service.shutdownNow();
+
+        return res;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/ActivitiDetector.java
----------------------------------------------------------------------
diff --git a/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/ActivitiDetector.java b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/ActivitiDetector.java
new file mode 100644
index 0000000..f16dbe6
--- /dev/null
+++ b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/ActivitiDetector.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.fit.server.reference;
+
+import org.apache.syncope.common.rest.api.service.SyncopeService;
+
+public class ActivitiDetector {
+
+    public static boolean isActivitiEnabledForUsers(final SyncopeService syncopeService) {
+        return syncopeService.info().getUserWorkflowAdapter().indexOf("Activiti") != -1;
+    }
+
+    public static boolean isActivitiEnabledForRoles(final SyncopeService syncopeService) {
+        return syncopeService.info().getRoleWorkflowAdapter().indexOf("Activiti") != -1;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/AuthenticationITCase.java
----------------------------------------------------------------------
diff --git a/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/AuthenticationITCase.java b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/AuthenticationITCase.java
new file mode 100644
index 0000000..5b3b4b0
--- /dev/null
+++ b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/AuthenticationITCase.java
@@ -0,0 +1,440 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.fit.server.reference;
+
+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 static org.junit.Assert.fail;
+
+import java.security.AccessControlException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.core.Response;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.mod.StatusMod;
+import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.BulkActionResult;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.PagedResult;
+import org.apache.syncope.common.lib.to.PlainSchemaTO;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.to.WorkflowFormPropertyTO;
+import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.CipherAlgorithm;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.ResourceDeassociationActionType;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.common.lib.wrap.EntitlementTO;
+import org.apache.syncope.common.lib.wrap.ResourceName;
+import org.apache.syncope.common.rest.api.CollectionWrapper;
+import org.apache.syncope.common.rest.api.service.EntitlementService;
+import org.apache.syncope.common.rest.api.service.SchemaService;
+import org.apache.syncope.common.rest.api.service.UserSelfService;
+import org.apache.syncope.common.rest.api.service.UserService;
+import org.apache.syncope.server.misc.security.Encryptor;
+import org.junit.Assume;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class AuthenticationITCase extends AbstractITCase {
+
+    private int getFailedLogins(UserService testUserService, long userId) {
+        UserTO readUserTO = testUserService.read(userId);
+        assertNotNull(readUserTO);
+        assertNotNull(readUserTO.getFailedLogins());
+        return readUserTO.getFailedLogins();
+    }
+
+    private void assertReadFails(UserService userService, long id) {
+        try {
+            userService.read(id);
+            fail("access should not work");
+        } catch (Exception e) {
+            assertNotNull(e);
+        }
+    }
+
+    @Test
+    public void testAdminEntitlements() {
+        // 1. as anonymous, read all available entitlements
+        List<EntitlementTO> allEntitlements = entitlementService.getAllEntitlements();
+        assertNotNull(allEntitlements);
+        assertFalse(allEntitlements.isEmpty());
+
+        // 2. as admin, read own entitlements
+        List<EntitlementTO> adminEntitlements = entitlementService.getOwnEntitlements();
+
+        assertEquals(new HashSet<String>(CollectionWrapper.unwrap(allEntitlements)),
+                new HashSet<String>(CollectionWrapper.unwrap(adminEntitlements)));
+    }
+
+    @Test
+    public void testUserSchemaAuthorization() {
+        // 0. create a role that can only read schemas
+        RoleTO authRoleTO = new RoleTO();
+        authRoleTO.setName("authRole" + getUUIDString());
+        authRoleTO.setParent(8L);
+        authRoleTO.getEntitlements().add("SCHEMA_READ");
+
+        authRoleTO = createRole(authRoleTO);
+        assertNotNull(authRoleTO);
+
+        String schemaName = "authTestSchema" + getUUIDString();
+
+        // 1. create a schema (as admin)
+        PlainSchemaTO schemaTO = new PlainSchemaTO();
+        schemaTO.setKey(schemaName);
+        schemaTO.setMandatoryCondition("false");
+        schemaTO.setType(AttrSchemaType.String);
+
+        PlainSchemaTO newPlainSchemaTO = createSchema(AttributableType.USER, SchemaType.PLAIN, schemaTO);
+        assertEquals(schemaTO, newPlainSchemaTO);
+
+        // 2. create an user with the role created above (as admin)
+        UserTO userTO = UserITCase.getUniqueSampleTO("auth@test.org");
+
+        MembershipTO membershipTO = new MembershipTO();
+        membershipTO.setRoleId(authRoleTO.getKey());
+        AttrTO testAttrTO = new AttrTO();
+        testAttrTO.setSchema("testAttribute");
+        testAttrTO.getValues().add("a value");
+        membershipTO.getPlainAttrs().add(testAttrTO);
+        userTO.getMemberships().add(membershipTO);
+
+        userTO = createUser(userTO);
+        assertNotNull(userTO);
+
+        // 3. read the schema created above (as admin) - success
+        schemaTO = schemaService.read(AttributableType.USER, SchemaType.PLAIN, schemaName);
+        assertNotNull(schemaTO);
+
+        // 4. read the schema created above (as user) - success
+        SchemaService schemaService2 = clientFactory.create(userTO.getUsername(), "password123").getService(
+                SchemaService.class);
+
+        schemaTO = schemaService2.read(AttributableType.USER, SchemaType.PLAIN, schemaName);
+        assertNotNull(schemaTO);
+
+        // 5. update the schema create above (as user) - failure
+        try {
+            schemaService2.update(AttributableType.ROLE, SchemaType.PLAIN, schemaName, schemaTO);
+            fail("Schemaupdate as user schould not work");
+        } catch (SyncopeClientException e) {
+            assertNotNull(e);
+            assertEquals(Response.Status.UNAUTHORIZED, e.getType().getResponseStatus());
+        } catch (AccessControlException e) {
+            // CXF Service will throw this exception
+            assertNotNull(e);
+        }
+
+        assertEquals(0, getFailedLogins(userService, userTO.getKey()));
+    }
+
+    @Test
+    public void testUserRead() {
+        UserTO userTO = UserITCase.getUniqueSampleTO("testuserread@test.org");
+
+        MembershipTO membershipTO = new MembershipTO();
+        membershipTO.setRoleId(7L);
+        AttrTO testAttrTO = new AttrTO();
+        testAttrTO.setSchema("testAttribute");
+        testAttrTO.getValues().add("a value");
+        membershipTO.getPlainAttrs().add(testAttrTO);
+        userTO.getMemberships().add(membershipTO);
+
+        userTO = createUser(userTO);
+        assertNotNull(userTO);
+
+        UserService userService2 = clientFactory.create(userTO.getUsername(), "password123").
+                getService(UserService.class);
+
+        UserTO readUserTO = userService2.read(1L);
+        assertNotNull(readUserTO);
+
+        UserService userService3 = clientFactory.create("verdi", ADMIN_PWD).getService(UserService.class);
+
+        SyncopeClientException exception = null;
+        try {
+            userService3.read(1L);
+            fail();
+        } catch (SyncopeClientException e) {
+            exception = e;
+        }
+        assertNotNull(exception);
+        assertEquals(ClientExceptionType.UnauthorizedRole, exception.getType());
+    }
+
+    @Test
+    public void testUserSearch() {
+        UserTO userTO = UserITCase.getUniqueSampleTO("testusersearch@test.org");
+
+        MembershipTO membershipTO = new MembershipTO();
+        membershipTO.setRoleId(7L);
+        AttrTO testAttrTO = new AttrTO();
+        testAttrTO.setSchema("testAttribute");
+        testAttrTO.getValues().add("a value");
+        membershipTO.getPlainAttrs().add(testAttrTO);
+        userTO.getMemberships().add(membershipTO);
+
+        userTO = createUser(userTO);
+        assertNotNull(userTO);
+
+        UserService userService2 = clientFactory.create(userTO.getUsername(), "password123").
+                getService(UserService.class);
+
+        PagedResult<UserTO> matchedUsers = userService2.search(
+                SyncopeClient.getUserSearchConditionBuilder().isNotNull("loginDate").query());
+        assertNotNull(matchedUsers);
+        assertFalse(matchedUsers.getResult().isEmpty());
+        Set<Long> userIds = new HashSet<Long>(matchedUsers.getResult().size());
+        for (UserTO user : matchedUsers.getResult()) {
+            userIds.add(user.getKey());
+        }
+        assertTrue(userIds.contains(1L));
+
+        UserService userService3 = clientFactory.create("verdi", "password").getService(UserService.class);
+
+        matchedUsers = userService3.search(
+                SyncopeClient.getUserSearchConditionBuilder().isNotNull("loginDate").query());
+        assertNotNull(matchedUsers);
+
+        userIds = new HashSet<>(matchedUsers.getResult().size());
+
+        for (UserTO user : matchedUsers.getResult()) {
+            userIds.add(user.getKey());
+        }
+        assertFalse(userIds.contains(1L));
+    }
+
+    @Test
+    public void checkFailedLogins() {
+        UserTO userTO = UserITCase.getUniqueSampleTO("checkFailedLogin@syncope.apache.org");
+
+        MembershipTO membershipTO = new MembershipTO();
+        membershipTO.setRoleId(7L);
+        AttrTO testAttrTO = new AttrTO();
+        testAttrTO.setSchema("testAttribute");
+        testAttrTO.getValues().add("a value");
+        membershipTO.getPlainAttrs().add(testAttrTO);
+        userTO.getMemberships().add(membershipTO);
+
+        userTO = createUser(userTO);
+        assertNotNull(userTO);
+        long userId = userTO.getKey();
+
+        UserService userService2 = clientFactory.create(userTO.getUsername(), "password123").getService(
+                UserService.class);
+        assertEquals(0, getFailedLogins(userService2, userId));
+
+        // authentications failed ...
+        UserService userService3 = clientFactory.create(userTO.getUsername(), "wrongpwd1").getService(
+                UserService.class);
+        assertReadFails(userService3, userId);
+        assertReadFails(userService3, userId);
+
+        assertEquals(2, getFailedLogins(userService, userId));
+
+        UserService userService4 = clientFactory.create(userTO.getUsername(), "password123").getService(
+                UserService.class);
+        assertEquals(0, getFailedLogins(userService4, userId));
+    }
+
+    @Test
+    public void checkUserSuspension() {
+        UserTO userTO = UserITCase.getUniqueSampleTO("checkSuspension@syncope.apache.org");
+
+        MembershipTO membershipTO = new MembershipTO();
+        membershipTO.setRoleId(7L);
+        AttrTO testAttrTO = new AttrTO();
+        testAttrTO.setSchema("testAttribute");
+        testAttrTO.getValues().add("a value");
+        membershipTO.getPlainAttrs().add(testAttrTO);
+        userTO.getMemberships().add(membershipTO);
+
+        userTO = createUser(userTO);
+        long userId = userTO.getKey();
+        assertNotNull(userTO);
+
+        UserService userService2 = clientFactory.create(userTO.getUsername(), "password123").
+                getService(UserService.class);
+        assertEquals(0, getFailedLogins(userService2, userId));
+
+        // authentications failed ...
+        UserService userService3 = clientFactory.create(userTO.getUsername(), "wrongpwd1").
+                getService(UserService.class);
+        assertReadFails(userService3, userId);
+        assertReadFails(userService3, userId);
+        assertReadFails(userService3, userId);
+
+        assertEquals(3, getFailedLogins(userService, userId));
+
+        // last authentication before suspension
+        assertReadFails(userService3, userId);
+
+        userTO = userService.read(userTO.getKey());
+        assertNotNull(userTO);
+        assertNotNull(userTO.getFailedLogins());
+        assertEquals(3, userTO.getFailedLogins(), 0);
+        assertEquals("suspended", userTO.getStatus());
+
+        // Access with correct credentials should fail as user is suspended
+        userService2 = clientFactory.create(userTO.getUsername(), "password123").getService(UserService.class);
+        assertReadFails(userService2, userId);
+
+        StatusMod reactivate = new StatusMod();
+        reactivate.setType(StatusMod.ModType.REACTIVATE);
+        userTO = userService.status(userTO.getKey(), reactivate).readEntity(UserTO.class);
+        assertNotNull(userTO);
+        assertEquals("active", userTO.getStatus());
+
+        userService2 = clientFactory.create(userTO.getUsername(), "password123").getService(UserService.class);
+        assertEquals(0, getFailedLogins(userService2, userId));
+    }
+
+    @Test
+    public void issueSYNCOPE48() {
+        // Parent role, able to create users with role 1
+        RoleTO parentRole = new RoleTO();
+        parentRole.setName("parentAdminRole" + getUUIDString());
+        parentRole.getEntitlements().add("USER_CREATE");
+        parentRole.getEntitlements().add("ROLE_1");
+        parentRole.setParent(1L);
+        parentRole = createRole(parentRole);
+        assertNotNull(parentRole);
+
+        // Child role, with no entitlements
+        RoleTO childRole = new RoleTO();
+        childRole.setName("childAdminRole");
+        childRole.setParent(parentRole.getKey());
+
+        childRole = createRole(childRole);
+        assertNotNull(childRole);
+
+        // User with child role, created by admin
+        UserTO role1Admin = UserITCase.getUniqueSampleTO("syncope48admin@apache.org");
+        role1Admin.setPassword("password");
+        MembershipTO membershipTO = new MembershipTO();
+        membershipTO.setRoleId(childRole.getKey());
+        role1Admin.getMemberships().add(membershipTO);
+
+        role1Admin = createUser(role1Admin);
+        assertNotNull(role1Admin);
+
+        UserService userService2 = clientFactory.create(role1Admin.getUsername(), "password").getService(
+                UserService.class);
+
+        // User with role 1, created by user with child role created above
+        UserTO role1User = UserITCase.getUniqueSampleTO("syncope48user@apache.org");
+        membershipTO = new MembershipTO();
+        membershipTO.setRoleId(1L);
+        role1User.getMemberships().add(membershipTO);
+
+        Response response = userService2.create(role1User, true);
+        assertNotNull(response);
+        role1User = response.readEntity(UserTO.class);
+        assertNotNull(role1User);
+    }
+
+    @Test
+    public void issueSYNCOPE434() {
+        Assume.assumeTrue(ActivitiDetector.isActivitiEnabledForUsers(syncopeService));
+
+        // 1. create user with role 9 (users with role 9 are defined in workflow as subject to approval)
+        UserTO userTO = UserITCase.getUniqueSampleTO("createWithReject@syncope.apache.org");
+        MembershipTO membershipTO = new MembershipTO();
+        membershipTO.setRoleId(9L);
+        userTO.getMemberships().add(membershipTO);
+
+        userTO = createUser(userTO);
+        assertNotNull(userTO);
+        assertEquals("createApproval", userTO.getStatus());
+
+        // 2. try to authenticate: fail
+        EntitlementService myEntitlementService = clientFactory.create(userTO.getUsername(), "password123").
+                getService(EntitlementService.class);
+        try {
+            myEntitlementService.getOwnEntitlements();
+            fail();
+        } catch (AccessControlException e) {
+            assertNotNull(e);
+        }
+
+        // 3. approve user
+        WorkflowFormTO form = userWorkflowService.getFormForUser(userTO.getKey());
+        form = userWorkflowService.claimForm(form.getTaskId());
+        Map<String, WorkflowFormPropertyTO> props = form.getPropertyMap();
+        props.get("approve").setValue(Boolean.TRUE.toString());
+        form.getProperties().clear();
+        form.getProperties().addAll(props.values());
+        userTO = userWorkflowService.submitForm(form);
+        assertNotNull(userTO);
+        assertEquals("active", userTO.getStatus());
+
+        // 4. try to authenticate again: success
+        assertNotNull(myEntitlementService.getOwnEntitlements());
+    }
+
+    @Test
+    public void issueSYNCOPE164() throws Exception {
+        // 1. create user with db resource
+        UserTO user = UserITCase.getUniqueSampleTO("syncope164@syncope.apache.org");
+        user.setPassword("password1");
+        user.getResources().add(RESOURCE_NAME_TESTDB);
+        user = createUser(user);
+        assertNotNull(user);
+
+        // 2. unlink the resource from the created user
+        assertNotNull(userService.bulkDeassociation(user.getKey(),
+                ResourceDeassociationActionType.UNLINK,
+                CollectionWrapper.wrap(RESOURCE_NAME_TESTDB, ResourceName.class)).
+                readEntity(BulkActionResult.class));
+
+        // 3. change password on Syncope
+        UserMod userMod = new UserMod();
+        userMod.setKey(user.getKey());
+        userMod.setPassword("password2");
+        user = updateUser(userMod);
+        assertNotNull(user);
+
+        // 4. check that the db resource has still the initial password value
+        final JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
+        String value = jdbcTemplate.queryForObject(
+                "SELECT PASSWORD FROM test WHERE ID=?", String.class, user.getUsername());
+        assertEquals(Encryptor.getInstance().encode("password1", CipherAlgorithm.SHA1), value.toUpperCase());
+
+        // 5. successfully authenticate with old (on db resource) and new (on internal storage) password values
+        user = clientFactory.create(user.getUsername(), "password1").getService(UserSelfService.class).read();
+        assertNotNull(user);
+        user = clientFactory.create(user.getUsername(), "password2").getService(UserSelfService.class).read();
+        assertNotNull(user);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/CamelDetector.java
----------------------------------------------------------------------
diff --git a/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/CamelDetector.java b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/CamelDetector.java
new file mode 100644
index 0000000..81eaa4e
--- /dev/null
+++ b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/CamelDetector.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.fit.server.reference;
+
+import org.apache.syncope.common.rest.api.service.SyncopeService;
+
+public class CamelDetector {
+
+    public static boolean isCamelEnabledForUsers(final SyncopeService syncopeService) {
+        return syncopeService.info().getUserProvisioningManager().indexOf("Camel") != -1;
+    }
+
+    public static boolean isCamelEnabledForRoles(final SyncopeService syncopeService) {
+        return syncopeService.info().getRoleProvisioningManager().indexOf("Camel") != -1;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/CamelRouteITCase.java
----------------------------------------------------------------------
diff --git a/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/CamelRouteITCase.java b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/CamelRouteITCase.java
new file mode 100644
index 0000000..46d813e
--- /dev/null
+++ b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/CamelRouteITCase.java
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.fit.server.reference;
+
+import static org.apache.syncope.fit.server.reference.AbstractITCase.syncopeService;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+import org.apache.syncope.common.lib.to.CamelRouteTO;
+import org.apache.syncope.common.lib.to.PlainSchemaTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.common.lib.types.SubjectType;
+import org.junit.Assume;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class CamelRouteITCase extends AbstractITCase {
+
+    @Test
+    public void userRoutes() {
+        Assume.assumeTrue(CamelDetector.isCamelEnabledForUsers(syncopeService));
+
+        List<CamelRouteTO> userRoutes = camelRouteService.list(SubjectType.USER);
+        assertNotNull(userRoutes);
+        assertEquals(15, userRoutes.size());
+        for (CamelRouteTO route : userRoutes) {
+            assertNotNull(route.getContent());
+        }
+    }
+
+    @Test
+    public void roleRoutes() {
+        Assume.assumeTrue(CamelDetector.isCamelEnabledForRoles(syncopeService));
+
+        List<CamelRouteTO> roleRoutes = camelRouteService.list(SubjectType.ROLE);
+        assertNotNull(roleRoutes);
+        assertEquals(7, roleRoutes.size());
+        for (CamelRouteTO route : roleRoutes) {
+            assertNotNull(route.getContent());
+        }
+    }
+
+    private CamelRouteTO doUpdate(final String key, String content) {
+        CamelRouteTO route = camelRouteService.read(key);
+        route.setContent(content);
+        camelRouteService.update(route.getKey(), route);
+        //getting new route definition
+        return camelRouteService.read(key);
+    }
+
+    @Test
+    public void update() {
+        Assume.assumeTrue(CamelDetector.isCamelEnabledForUsers(syncopeService));
+
+        CamelRouteTO oldRoute = camelRouteService.read("createUser");
+        assertNotNull(oldRoute);
+        String routeContent = "<route id=\"createUser\">\n"
+                + "  <from uri=\"direct:createUser\"/>\n"
+                + "  <setProperty propertyName=\"actual\">\n"
+                + "    <simple>${body}</simple>\n"
+                + "  </setProperty>\n"
+                + "  <doTry>\n"
+                + "    <bean ref=\"uwfAdapter\" method=\"create(${body},${property.disablePwdPolicyCheck},\n"
+                + "                             ${property.enabled},${property.storePassword})\"/>\n"
+                + "    <process ref=\"userCreateProcessor\" />\n"
+                + "    <to uri=\"direct:createPort\"/>\n"
+                + "    <to uri=\"log:myLog\"/>\n"
+                + "    <doCatch>        \n"
+                + "      <exception>java.lang.RuntimeException</exception>\n"
+                + "      <handled>\n"
+                + "        <constant>false</constant>\n"
+                + "      </handled>\n"
+                + "      <to uri=\"direct:createPort\"/>\n"
+                + "    </doCatch>\n"
+                + "  </doTry>\n"
+                + "</route>";
+        try {
+            CamelRouteTO route = doUpdate("createUser", routeContent);
+            assertEquals(routeContent, route.getContent());
+        } finally {
+            doUpdate(oldRoute.getKey(), oldRoute.getContent());
+        }
+    }
+
+    @Test
+    public void scriptingUpdate() {
+        Assume.assumeTrue(CamelDetector.isCamelEnabledForUsers(syncopeService));
+
+        CamelRouteTO oldRoute = camelRouteService.read("createUser");
+        //updating route content including new attribute management
+        String routeContent = "<route id=\"createUser\">\n"
+                + "  <from uri=\"direct:createUser\"/>\n"
+                + "  <setProperty propertyName=\"actual\">\n"
+                + "    <simple>${body}</simple>\n"
+                + "  </setProperty>\n"
+                + "  <setBody>\n"
+                + "   <groovy>\n"
+                + "       request.body.getPlainAttrs().get(3).getValues().set(0,\"true\")\n"
+                + "       return request.body\n"
+                + "   </groovy>\n"
+                + "  </setBody>\n"
+                + "  <doTry>\n"
+                + "      <bean ref=\"uwfAdapter\" method=\"create(${body},${property.disablePwdPolicyCheck},\n"
+                + "                            ${property.enabled},${property.storePassword})\"/>\n"
+                + "      <process ref=\"userCreateProcessor\" />\n"
+                + "      <to uri=\"direct:createPort\"/>\n"
+                + "      <doCatch>        \n"
+                + "      <exception>java.lang.RuntimeException</exception>\n"
+                + "          <handled>\n"
+                + "           <constant>false</constant>\n"
+                + "          </handled>\n"
+                + "      <to uri=\"direct:createPort\"/>\n"
+                + "      </doCatch>\n"
+                + "   </doTry>\n"
+                + "</route>";
+        try {
+            doUpdate("createUser", routeContent);
+
+            //creating new schema attribute for user
+            PlainSchemaTO schemaTO = new PlainSchemaTO();
+            schemaTO.setKey("camelAttribute");
+            schemaTO.setType(AttrSchemaType.String);
+            createSchema(AttributableType.USER, SchemaType.PLAIN, schemaTO);
+
+            UserTO userTO = new UserTO();
+            String userId = getUUIDString() + "camelUser@syncope.apache.org";
+            userTO.setUsername(userId);
+            userTO.setPassword("password");
+            userTO.getPlainAttrs().add(attrTO("userId", userId));
+            userTO.getPlainAttrs().add(attrTO("fullname", userId));
+            userTO.getPlainAttrs().add(attrTO("surname", userId));
+            userTO.getPlainAttrs().add(attrTO("camelAttribute", "false"));
+
+            userTO = createUser(userTO);
+            assertNotNull(userTO);
+            assertEquals("true", userTO.getPlainAttrs().get(3).getValues().get(0));
+        } finally {
+            doUpdate(oldRoute.getKey(), oldRoute.getContent());
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/ConfigurationITCase.java
----------------------------------------------------------------------
diff --git a/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/ConfigurationITCase.java b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/ConfigurationITCase.java
new file mode 100644
index 0000000..bf35a9c
--- /dev/null
+++ b/syncope620/fit/server-reference/src/test/java/org/apache/syncope/fit/server/reference/ConfigurationITCase.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.fit.server.reference;
+
+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 static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.ConfTO;
+import org.apache.syncope.common.lib.to.PlainSchemaTO;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class ConfigurationITCase extends AbstractITCase {
+
+    @Test
+    public void create() {
+        PlainSchemaTO testKey = new PlainSchemaTO();
+        testKey.setKey("testKey");
+        testKey.setType(AttrSchemaType.String);
+        createSchema(AttributableType.CONFIGURATION, SchemaType.PLAIN, testKey);
+
+        AttrTO conf = new AttrTO();
+        conf.setSchema("testKey");
+        conf.getValues().add("testValue");
+
+        configurationService.set(conf.getSchema(), conf);
+
+        AttrTO actual = configurationService.read(conf.getSchema());
+        assertEquals(actual, conf);
+    }
+
+    @Test
+    public void delete() throws UnsupportedEncodingException {
+        try {
+            configurationService.delete("nonExistent");
+        } catch (SyncopeClientException e) {
+            assertEquals(Response.Status.NOT_FOUND, e.getType().getResponseStatus());
+        }
+
+        AttrTO tokenLength = configurationService.read("token.length");
+
+        configurationService.delete("token.length");
+        try {
+            configurationService.read("token.length");
+        } catch (SyncopeClientException e) {
+            assertEquals(Response.Status.NOT_FOUND, e.getType().getResponseStatus());
+        }
+
+        configurationService.set(tokenLength.getSchema(), tokenLength);
+
+        AttrTO actual = configurationService.read(tokenLength.getSchema());
+        assertEquals(actual, tokenLength);
+    }
+
+    @Test
+    public void list() {
+        ConfTO wholeConf = configurationService.list();
+        assertNotNull(wholeConf);
+        for (AttrTO conf : wholeConf.getPlainAttrs()) {
+            assertNotNull(conf);
+        }
+    }
+
+    @Test
+    public void read() {
+        AttrTO conf = configurationService.read("token.expireTime");
+        assertNotNull(conf);
+    }
+
+    @Test
+    public void update() {
+        AttrTO expireTime = configurationService.read("token.expireTime");
+        int value = Integer.parseInt(expireTime.getValues().get(0));
+        value++;
+        expireTime.getValues().set(0, value + "");
+
+        configurationService.set(expireTime.getSchema(), expireTime);
+
+        AttrTO newConfigurationTO = configurationService.read(expireTime.getSchema());
+        assertEquals(expireTime, newConfigurationTO);
+    }
+
+    @Test
+    public void dbExport() throws IOException {
+        Response response = configurationService.export();
+        assertNotNull(response);
+        assertEquals(Response.Status.OK.getStatusCode(), response.getStatusInfo().getStatusCode());
+        assertTrue(response.getMediaType().toString().startsWith(MediaType.TEXT_XML));
+        String contentDisposition = response.getHeaderString(HttpHeaders.CONTENT_DISPOSITION);
+        assertNotNull(contentDisposition);
+
+        Object entity = response.getEntity();
+        assertTrue(entity instanceof InputStream);
+        String configExport = IOUtils.toString((InputStream) entity, SyncopeConstants.DEFAULT_ENCODING);
+        assertFalse(configExport.isEmpty());
+        assertTrue(configExport.length() > 1000);
+    }
+
+    @Test
+    public void issueSYNCOPE418() {
+        PlainSchemaTO failing = new PlainSchemaTO();
+        failing.setKey("http://schemas.examples.org/security/authorization/organizationUnit");
+        failing.setType(AttrSchemaType.String);
+
+        try {
+            createSchema(AttributableType.CONFIGURATION, SchemaType.PLAIN, failing);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidPlainSchema, e.getType());
+
+            assertNotNull(e.getElements());
+            assertEquals(1, e.getElements().size());
+            assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidName.name()));
+        }
+    }
+
+    @Test
+    public void issueSYNCOPE629() throws IOException {
+        PlainSchemaTO membershipKey = new PlainSchemaTO();
+        membershipKey.setKey("membershipKey" + getUUIDString());
+        membershipKey.setType(AttrSchemaType.String);
+        createSchema(AttributableType.MEMBERSHIP, SchemaType.PLAIN, membershipKey);
+
+        PlainSchemaTO roleKey = new PlainSchemaTO();
+        roleKey.setKey("roleKey" + getUUIDString());
+        roleKey.setType(AttrSchemaType.String);
+        createSchema(AttributableType.ROLE, SchemaType.PLAIN, roleKey);
+
+        RoleTO roleTO = new RoleTO();
+        roleTO.setName("aRole" + getUUIDString());
+        roleTO.getMAttrTemplates().add(membershipKey.getKey());
+        roleTO.getRAttrTemplates().add(roleKey.getKey());
+        roleTO = createRole(roleTO);
+
+        try {
+            Response response = configurationService.export();
+            assertNotNull(response);
+            assertEquals(Response.Status.OK.getStatusCode(), response.getStatusInfo().getStatusCode());
+            assertTrue(response.getMediaType().toString().startsWith(MediaType.TEXT_XML));
+            String contentDisposition = response.getHeaderString(HttpHeaders.CONTENT_DISPOSITION);
+            assertNotNull(contentDisposition);
+
+            Object entity = response.getEntity();
+            assertTrue(entity instanceof InputStream);
+            String configExport = IOUtils.toString((InputStream) entity, SyncopeConstants.DEFAULT_ENCODING);
+            assertFalse(configExport.isEmpty());
+            assertTrue(configExport.length() > 1000);
+
+            String[] result = StringUtils.substringsBetween(configExport, "<RPLAINATTRTEMPLATE", "/>");
+            assertNotNull(result);
+            boolean rattrExists = false;
+            for (String entry : result) {
+                if (entry.contains(roleKey.getKey())) {
+                    rattrExists = true;
+                }
+            }
+            assertTrue(rattrExists);
+
+            result = StringUtils.substringsBetween(configExport, "<MPLAINATTRTEMPLATE", "/>");
+            assertNotNull(result);
+            boolean mattrExists = false;
+            for (String entry : result) {
+                if (entry.contains(membershipKey.getKey())) {
+                    mattrExists = true;
+                }
+            }
+            assertTrue(mattrExists);
+        } finally {
+            deleteRole(roleTO.getKey());
+        }
+    }
+}