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 2017/11/14 16:24:22 UTC

[1/6] syncope git commit: [SYNCOPE-152] SCIM configuration including attribute mapping + console extension

Repository: syncope
Updated Branches:
  refs/heads/2_0_X 460bd265e -> 1aa7bcaff
  refs/heads/master e3ac8999d -> 7cd228925


http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java
deleted file mode 100644
index 73dbd5a..0000000
--- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.ext.scimv2.cxf.service;
-
-import java.util.Collections;
-import java.util.List;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.UriInfo;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.tuple.Pair;
-import org.apache.cxf.jaxrs.ext.MessageContext;
-import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.to.GroupTO;
-import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.syncope.core.logic.AbstractAnyLogic;
-import org.apache.syncope.core.logic.GroupLogic;
-import org.apache.syncope.core.logic.UserLogic;
-import org.apache.syncope.core.logic.scim.SearchCondConverter;
-import org.apache.syncope.core.persistence.api.dao.AnyDAO;
-import org.apache.syncope.core.persistence.api.dao.search.MembershipCond;
-import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
-import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
-import org.apache.syncope.core.spring.ApplicationContextProvider;
-import org.apache.syncope.ext.scimv2.api.data.Display;
-import org.apache.syncope.ext.scimv2.api.data.Group;
-import org.apache.syncope.ext.scimv2.api.data.ListResponse;
-import org.apache.syncope.ext.scimv2.api.data.Member;
-import org.apache.syncope.ext.scimv2.api.data.Meta;
-import org.apache.syncope.ext.scimv2.api.data.SCIMGroup;
-import org.apache.syncope.ext.scimv2.api.data.SCIMResource;
-import org.apache.syncope.ext.scimv2.api.data.SCIMUser;
-import org.apache.syncope.ext.scimv2.api.service.SCIMService;
-import org.apache.syncope.ext.scimv2.api.type.Function;
-import org.apache.syncope.ext.scimv2.api.type.Resource;
-import org.apache.syncope.ext.scimv2.api.type.SortOrder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-abstract class AbstractSCIMService<R extends SCIMResource> implements SCIMService<R> {
-
-    protected static final Logger LOG = LoggerFactory.getLogger(AbstractSCIMService.class);
-
-    @Context
-    protected UriInfo uriInfo;
-
-    @Context
-    protected MessageContext messageContext;
-
-    private UserLogic userLogic;
-
-    private GroupLogic groupLogic;
-
-    protected UserLogic userLogic() {
-        synchronized (this) {
-            if (userLogic == null) {
-                userLogic = ApplicationContextProvider.getApplicationContext().getBean(UserLogic.class);
-            }
-        }
-        return userLogic;
-    }
-
-    protected GroupLogic groupLogic() {
-        synchronized (this) {
-            if (groupLogic == null) {
-                groupLogic = ApplicationContextProvider.getApplicationContext().getBean(GroupLogic.class);
-            }
-        }
-        return groupLogic;
-    }
-
-    protected AbstractAnyLogic<?, ?> anyLogic(final Resource type) {
-        switch (type) {
-            case User:
-                return userLogic();
-
-            case Group:
-                return groupLogic();
-
-            default:
-                throw new UnsupportedOperationException();
-        }
-    }
-
-    protected SCIMUser toSCIMUser(final UserTO userTO, final String location) {
-        SCIMUser user = new SCIMUser(
-                userTO.getKey(),
-                Collections.singletonList(Resource.User.schema()),
-                new Meta(
-                        Resource.User,
-                        userTO.getCreationDate(),
-                        userTO.getLastChangeDate() == null
-                        ? userTO.getCreationDate() : userTO.getLastChangeDate(),
-                        userTO.getETagValue(),
-                        location),
-                userTO.getUsername(),
-                !userTO.isSuspended());
-
-        userTO.getMemberships().forEach(membership -> {
-            user.getGroups().add(new Group(
-                    membership.getGroupKey(),
-                    StringUtils.substringBefore(location, "/Users") + "/Groups/" + membership.getGroupKey(),
-                    membership.getGroupName(),
-                    Function.direct));
-        });
-        userTO.getDynMemberships().forEach(membership -> {
-            user.getGroups().add(new Group(
-                    membership.getGroupKey(),
-                    StringUtils.substringBefore(location, "/Users") + "/Groups/" + membership.getGroupKey(),
-                    membership.getGroupName(),
-                    Function.indirect));
-        });
-
-        userTO.getRoles().forEach(role -> {
-            user.getRoles().add(new Display(role, null));
-        });
-
-        return user;
-    }
-
-    protected SCIMGroup toSCIMGroup(final GroupTO groupTO, final String location) {
-        SCIMGroup group = new SCIMGroup(
-                groupTO.getKey(),
-                Collections.singletonList(Resource.Group.schema()),
-                new Meta(
-                        Resource.Group,
-                        groupTO.getCreationDate(),
-                        groupTO.getLastChangeDate() == null
-                        ? groupTO.getCreationDate() : groupTO.getLastChangeDate(),
-                        groupTO.getETagValue(),
-                        location),
-                groupTO.getName());
-
-        MembershipCond membCond = new MembershipCond();
-        membCond.setGroup(groupTO.getKey());
-        SearchCond searchCond = SearchCond.getLeafCond(membCond);
-
-        int count = userLogic().
-                search(searchCond, 1, 1, Collections.<OrderByClause>emptyList(), SyncopeConstants.ROOT_REALM, false).
-                getLeft();
-
-        for (int page = 1; page <= (count / AnyDAO.DEFAULT_PAGE_SIZE) + 1; page++) {
-            List<UserTO> users = userLogic().search(
-                    searchCond,
-                    page,
-                    AnyDAO.DEFAULT_PAGE_SIZE,
-                    Collections.<OrderByClause>emptyList(),
-                    SyncopeConstants.ROOT_REALM,
-                    false).
-                    getRight();
-            users.forEach(userTO -> {
-                group.getMembers().add(new Member(
-                        userTO.getKey(),
-                        StringUtils.substringBefore(location, "/Groups") + "/Users/" + userTO.getKey(),
-                        userTO.getUsername(),
-                        Resource.User));
-            });
-        }
-
-        return group;
-    }
-
-    @SuppressWarnings("unchecked")
-    protected ListResponse<R> doSearch(
-            final Resource type,
-            final Integer startIndex,
-            final Integer count,
-            final String filter,
-            final String sortBy,
-            final SortOrder sortOrder,
-            final List<String> attributes) {
-
-        if (type == null) {
-            throw new UnsupportedOperationException();
-        }
-
-        Pair<Integer, ? extends List<? extends AnyTO>> result = anyLogic(type).search(
-                StringUtils.isBlank(filter) ? null : SearchCondConverter.convert(filter),
-                startIndex == null || startIndex <= 1 ? 1 : (startIndex / AnyDAO.DEFAULT_PAGE_SIZE) + 1,
-                AnyDAO.DEFAULT_PAGE_SIZE,
-                Collections.<OrderByClause>emptyList(),
-                SyncopeConstants.ROOT_REALM,
-                false);
-
-        ListResponse<R> response = new ListResponse<>(
-                result.getLeft(), startIndex == null || startIndex <= 1 ? 1 : startIndex, AnyDAO.DEFAULT_PAGE_SIZE);
-
-        result.getRight().forEach(anyTO -> {
-            SCIMResource resource = null;
-            if (anyTO instanceof UserTO) {
-                resource = toSCIMUser(
-                        (UserTO) anyTO,
-                        uriInfo.getAbsolutePathBuilder().path(anyTO.getKey()).build().toASCIIString());
-            } else if (anyTO instanceof GroupTO) {
-                resource = toSCIMGroup(
-                        (GroupTO) anyTO,
-                        uriInfo.getAbsolutePathBuilder().path(anyTO.getKey()).build().toASCIIString());
-            }
-
-            if (resource != null) {
-                response.getResources().add((R) resource);
-            }
-        });
-
-        return response;
-    }
-
-    @Override
-    public ListResponse<R> search(
-            final Integer startIndex,
-            final Integer count,
-            final String filter,
-            final String sortBy,
-            final SortOrder sortOrder,
-            final List<String> attributes) {
-
-        return doSearch(null, startIndex, count, filter, sortBy, sortOrder, attributes);
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractService.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractService.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractService.java
new file mode 100644
index 0000000..6f61e4c
--- /dev/null
+++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractService.java
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.ext.scimv2.cxf.service;
+
+import java.util.Collections;
+import java.util.List;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.cxf.jaxrs.ext.MessageContext;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.core.logic.AbstractAnyLogic;
+import org.apache.syncope.core.logic.GroupLogic;
+import org.apache.syncope.core.logic.SCIMDataBinder;
+import org.apache.syncope.core.logic.UserLogic;
+import org.apache.syncope.core.logic.scim.SearchCondConverter;
+import org.apache.syncope.core.persistence.api.dao.AnyDAO;
+import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
+import org.apache.syncope.ext.scimv2.api.data.ListResponse;
+import org.apache.syncope.ext.scimv2.api.data.SCIMResource;
+import org.apache.syncope.ext.scimv2.api.type.Resource;
+import org.apache.syncope.ext.scimv2.api.type.SortOrder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.syncope.ext.scimv2.api.service.SearchService;
+
+abstract class AbstractService<R extends SCIMResource> implements SearchService<R> {
+
+    protected static final Logger LOG = LoggerFactory.getLogger(AbstractService.class);
+
+    @Context
+    protected UriInfo uriInfo;
+
+    @Context
+    protected MessageContext messageContext;
+
+    private UserLogic userLogic;
+
+    private GroupLogic groupLogic;
+
+    private SCIMDataBinder binder;
+
+    protected UserLogic userLogic() {
+        synchronized (this) {
+            if (userLogic == null) {
+                userLogic = ApplicationContextProvider.getApplicationContext().getBean(UserLogic.class);
+            }
+        }
+        return userLogic;
+    }
+
+    protected GroupLogic groupLogic() {
+        synchronized (this) {
+            if (groupLogic == null) {
+                groupLogic = ApplicationContextProvider.getApplicationContext().getBean(GroupLogic.class);
+            }
+        }
+        return groupLogic;
+    }
+
+    protected SCIMDataBinder binder() {
+        synchronized (this) {
+            if (binder == null) {
+                binder = ApplicationContextProvider.getApplicationContext().getBean(SCIMDataBinder.class);
+            }
+        }
+        return binder;
+    }
+
+    protected AbstractAnyLogic<?, ?> anyLogic(final Resource type) {
+        switch (type) {
+            case User:
+                return userLogic();
+
+            case Group:
+                return groupLogic();
+
+            default:
+                throw new UnsupportedOperationException();
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    protected ListResponse<R> doSearch(
+            final Resource type,
+            final Integer startIndex,
+            final Integer count,
+            final String filter,
+            final String sortBy,
+            final SortOrder sortOrder,
+            final List<String> attributes) {
+
+        if (type == null) {
+            throw new UnsupportedOperationException();
+        }
+
+        Pair<Integer, ? extends List<? extends AnyTO>> result = anyLogic(type).search(
+                StringUtils.isBlank(filter) ? null : SearchCondConverter.convert(filter),
+                startIndex == null || startIndex <= 1 ? 1 : (startIndex / AnyDAO.DEFAULT_PAGE_SIZE) + 1,
+                AnyDAO.DEFAULT_PAGE_SIZE,
+                Collections.<OrderByClause>emptyList(),
+                SyncopeConstants.ROOT_REALM,
+                false);
+
+        ListResponse<R> response = new ListResponse<>(
+                result.getLeft(), startIndex == null || startIndex <= 1 ? 1 : startIndex, AnyDAO.DEFAULT_PAGE_SIZE);
+
+        result.getRight().forEach(anyTO -> {
+            SCIMResource resource = null;
+            if (anyTO instanceof UserTO) {
+                resource = binder().toSCIMUser(
+                        (UserTO) anyTO,
+                        uriInfo.getAbsolutePathBuilder().path(anyTO.getKey()).build().toASCIIString());
+            } else if (anyTO instanceof GroupTO) {
+                resource = binder().toSCIMGroup(
+                        (GroupTO) anyTO,
+                        uriInfo.getAbsolutePathBuilder().path(anyTO.getKey()).build().toASCIIString());
+            }
+
+            if (resource != null) {
+                response.getResources().add((R) resource);
+            }
+        });
+
+        return response;
+    }
+
+    @Override
+    public ListResponse<R> search(
+            final Integer startIndex,
+            final Integer count,
+            final String filter,
+            final String sortBy,
+            final SortOrder sortOrder,
+            final List<String> attributes) {
+
+        return doSearch(null, startIndex, count, filter, sortBy, sortOrder, attributes);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java
index 85b9198..d03b57c 100644
--- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java
+++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java
@@ -27,7 +27,7 @@ import org.apache.syncope.ext.scimv2.api.service.GroupService;
 import org.apache.syncope.ext.scimv2.api.type.Resource;
 import org.apache.syncope.ext.scimv2.api.type.SortOrder;
 
-public class GroupServiceImpl extends AbstractSCIMService<SCIMGroup> implements GroupService {
+public class GroupServiceImpl extends AbstractService<SCIMGroup> implements GroupService {
 
     @Override
     public Response create() {
@@ -38,7 +38,7 @@ public class GroupServiceImpl extends AbstractSCIMService<SCIMGroup> implements
 
     @Override
     public SCIMGroup read(final String id) {
-        return toSCIMGroup(groupLogic().read(id), uriInfo.getAbsolutePathBuilder().build().toASCIIString());
+        return binder().toSCIMGroup(groupLogic().read(id), uriInfo.getAbsolutePathBuilder().build().toASCIIString());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/RootServiceImpl.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/RootServiceImpl.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/RootServiceImpl.java
deleted file mode 100644
index 6038f2b..0000000
--- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/RootServiceImpl.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.ext.scimv2.cxf.service;
-
-import java.util.List;
-import javax.ws.rs.core.Response;
-import org.apache.syncope.core.logic.RootLogic;
-import org.apache.syncope.core.spring.ApplicationContextProvider;
-import org.apache.syncope.ext.scimv2.api.data.ResourceType;
-import org.apache.syncope.ext.scimv2.api.data.SCIMResource;
-import org.apache.syncope.ext.scimv2.api.data.ServiceProviderConfig;
-import org.apache.syncope.ext.scimv2.api.service.RootService;
-
-public class RootServiceImpl extends AbstractSCIMService<SCIMResource> implements RootService {
-
-    private RootLogic rootLogic;
-
-    protected RootLogic rootLogic() {
-        synchronized (this) {
-            if (rootLogic == null) {
-                rootLogic = ApplicationContextProvider.getApplicationContext().getBean(RootLogic.class);
-            }
-        }
-        return rootLogic;
-    }
-
-    @Override
-    public ServiceProviderConfig serviceProviderConfig() {
-        return rootLogic().serviceProviderConfig();
-    }
-
-    @Override
-    public List<ResourceType> resourceTypes() {
-        return rootLogic().resourceTypes(uriInfo.getAbsolutePathBuilder());
-    }
-
-    @Override
-    public ResourceType resourceType(final String type) {
-        return rootLogic().resourceType(uriInfo.getAbsolutePathBuilder(), type);
-    }
-
-    @Override
-    public Response schemas() {
-        return Response.ok(rootLogic().schemas()).build();
-    }
-
-    @Override
-    public Response schema(final String schema) {
-        return Response.ok(rootLogic().schema(schema)).build();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMServiceImpl.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMServiceImpl.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMServiceImpl.java
new file mode 100644
index 0000000..65e4ad1
--- /dev/null
+++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMServiceImpl.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.ext.scimv2.cxf.service;
+
+import java.util.List;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.core.logic.SCIMLogic;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
+import org.apache.syncope.ext.scimv2.api.data.ResourceType;
+import org.apache.syncope.ext.scimv2.api.data.SCIMResource;
+import org.apache.syncope.ext.scimv2.api.data.ServiceProviderConfig;
+import org.apache.syncope.ext.scimv2.api.service.SCIMService;
+
+public class SCIMServiceImpl extends AbstractService<SCIMResource> implements SCIMService {
+
+    private SCIMLogic scimLogic;
+
+    private SCIMLogic scimLogic() {
+        synchronized (this) {
+            if (scimLogic == null) {
+                scimLogic = ApplicationContextProvider.getApplicationContext().getBean(SCIMLogic.class);
+            }
+        }
+        return scimLogic;
+    }
+
+    @Override
+    public ServiceProviderConfig serviceProviderConfig() {
+        return scimLogic().serviceProviderConfig(uriInfo.getAbsolutePathBuilder());
+    }
+
+    @Override
+    public List<ResourceType> resourceTypes() {
+        return scimLogic().resourceTypes(uriInfo.getAbsolutePathBuilder());
+    }
+
+    @Override
+    public ResourceType resourceType(final String type) {
+        return scimLogic().resourceType(uriInfo.getAbsolutePathBuilder(), type);
+    }
+
+    @Override
+    public Response schemas() {
+        return Response.ok(scimLogic().schemas()).build();
+    }
+
+    @Override
+    public Response schema(final String schema) {
+        return Response.ok(scimLogic().schema(schema)).build();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/UserServiceImpl.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/UserServiceImpl.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/UserServiceImpl.java
index c12ed6c..67b9b47 100644
--- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/UserServiceImpl.java
+++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/UserServiceImpl.java
@@ -27,7 +27,7 @@ import org.apache.syncope.ext.scimv2.api.service.UserService;
 import org.apache.syncope.ext.scimv2.api.type.Resource;
 import org.apache.syncope.ext.scimv2.api.type.SortOrder;
 
-public class UserServiceImpl extends AbstractSCIMService<SCIMUser> implements UserService {
+public class UserServiceImpl extends AbstractService<SCIMUser> implements UserService {
 
     @Override
     public Response create() {
@@ -38,7 +38,7 @@ public class UserServiceImpl extends AbstractSCIMService<SCIMUser> implements Us
 
     @Override
     public SCIMUser read(final String id) {
-        return toSCIMUser(userLogic().read(id), uriInfo.getAbsolutePathBuilder().build().toASCIIString());
+        return binder().toSCIMUser(userLogic().read(id), uriInfo.getAbsolutePathBuilder().build().toASCIIString());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/fit/console-reference/pom.xml
----------------------------------------------------------------------
diff --git a/fit/console-reference/pom.xml b/fit/console-reference/pom.xml
index 3ceedf0..253b043 100644
--- a/fit/console-reference/pom.xml
+++ b/fit/console-reference/pom.xml
@@ -69,6 +69,12 @@ under the License.
     </dependency>
     
     <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-client-console</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
     </dependency>

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/fit/console-reference/src/test/resources/rebel.xml
----------------------------------------------------------------------
diff --git a/fit/console-reference/src/test/resources/rebel.xml b/fit/console-reference/src/test/resources/rebel.xml
index f1189d5..cfd69c9 100644
--- a/fit/console-reference/src/test/resources/rebel.xml
+++ b/fit/console-reference/src/test/resources/rebel.xml
@@ -32,6 +32,8 @@ under the License.
     </dir>
     <dir name="${basedir}/../../ext/saml2sp/client-console/target/classes">
     </dir>
+    <dir name="${basedir}/../../ext/scimv2/client-console/target/classes">
+    </dir>
   </classpath>
 
   <web>
@@ -51,6 +53,10 @@ under the License.
       <dir name="${basedir}/../../ext/saml2sp/client-console/target/classes">
       </dir>
     </link>
+    <link target="/">
+      <dir name="${basedir}/../../ext/scimv2/client-console/target/classes">
+      </dir>
+    </link>
   </web>
 
 </application>

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/fit/core-reference/pom.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/pom.xml b/fit/core-reference/pom.xml
index ab9eb38..5284b9e 100644
--- a/fit/core-reference/pom.xml
+++ b/fit/core-reference/pom.xml
@@ -165,7 +165,25 @@ under the License.
       <artifactId>syncope-ext-saml2sp-client-console</artifactId>
       <version>${project.version}</version>
       <scope>test</scope>
-    </dependency>  
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-rest-cxf</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-scim-rest-cxf</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-client-console</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-test</artifactId>
@@ -1058,6 +1076,11 @@ under the License.
         
         <dependency>
           <groupId>org.apache.syncope.ext.scimv2</groupId>
+          <artifactId>syncope-ext-scimv2-rest-cxf</artifactId>
+          <version>${project.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.syncope.ext.scimv2</groupId>
           <artifactId>syncope-ext-scimv2-scim-rest-cxf</artifactId>
           <version>${project.version}</version>
         </dependency>

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/fit/core-reference/src/main/resources/all/scimv2-logic.properties
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/all/scimv2-logic.properties b/fit/core-reference/src/main/resources/all/scimv2-logic.properties
deleted file mode 100644
index 2d85a37..0000000
--- a/fit/core-reference/src/main/resources/all/scimv2-logic.properties
+++ /dev/null
@@ -1,21 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-conf.directory=${conf.directory}
-
-bulk.maxOperations=1000
-bulk.maxPayloadSize=1048576
-filter.maxResults=200

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
index 97667c3..c31be40 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
@@ -90,6 +90,7 @@ import org.apache.syncope.common.rest.api.service.ResourceHistoryService;
 import org.apache.syncope.common.rest.api.service.RoleService;
 import org.apache.syncope.common.rest.api.service.SAML2IdPService;
 import org.apache.syncope.common.rest.api.service.SAML2SPService;
+import org.apache.syncope.common.rest.api.service.SCIMConfService;
 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;
@@ -243,6 +244,8 @@ public abstract class AbstractITCase {
 
     protected static SAML2IdPService saml2IdPService;
 
+    protected static SCIMConfService scimConfService;
+
     @BeforeAll
     public static void securitySetup() {
         InputStream propStream = null;
@@ -311,6 +314,7 @@ public abstract class AbstractITCase {
         camelRouteService = adminClient.getService(CamelRouteService.class);
         saml2SpService = adminClient.getService(SAML2SPService.class);
         saml2IdPService = adminClient.getService(SAML2IdPService.class);
+        scimConfService = adminClient.getService(SCIMConfService.class);
     }
 
     protected static String getUUIDString() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
index cc8a92e..cc582b5 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
@@ -21,6 +21,7 @@ package org.apache.syncope.fit.core;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assumptions.assumeTrue;
 
@@ -37,6 +38,8 @@ import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.scim.SCIMConf;
+import org.apache.syncope.common.lib.scim.SCIMUserConf;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.ext.scimv2.api.SCIMConstants;
@@ -154,6 +157,34 @@ public class SCIMITCase extends AbstractITCase {
     }
 
     @Test
+    public void conf() {
+        assumeTrue(SCIMDetector.isSCIMAvailable(webClient()));
+
+        SCIMConf conf = scimConfService.get();
+        assertNotNull(conf);
+
+        SCIMUserConf userConf = conf.getUserConf();
+        if (userConf == null) {
+            userConf = new SCIMUserConf();
+            conf.setUserConf(userConf);
+        }
+        assertNull(userConf.getDisplayName());
+        userConf.setDisplayName("cn");
+
+        scimConfService.set(conf);
+
+        Response response = webClient().path("Users").path("1417acbe-cbf6-4277-9372-e75e04f97000").get();
+        assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+        assertEquals(
+                SCIMConstants.APPLICATION_SCIM_JSON,
+                StringUtils.substringBefore(response.getHeaderString(HttpHeaders.CONTENT_TYPE), ";"));
+
+        SCIMUser user = response.readEntity(SCIMUser.class);
+        assertNotNull(user);
+        assertEquals("Rossini, Gioacchino", user.getDisplayName());
+    }
+
+    @Test
     public void list() throws IOException {
         assumeTrue(SCIMDetector.isSCIMAvailable(webClient()));
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/fit/core-reference/src/test/resources/rebel.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/rebel.xml b/fit/core-reference/src/test/resources/rebel.xml
index c0f9331..da4b4b1 100644
--- a/fit/core-reference/src/test/resources/rebel.xml
+++ b/fit/core-reference/src/test/resources/rebel.xml
@@ -91,6 +91,12 @@ under the License.
     </dir>
     <dir name="${basedir}/../../ext/elasticsearch/persistence-jpa/target/classes">
     </dir>
+    <dir name="${basedir}/../../ext/scimv2/common-lib/target/classes">
+    </dir>
+    <dir name="${basedir}/../../ext/scimv2/rest-api/target/classes">
+    </dir>
+    <dir name="${basedir}/../../ext/scimv2/rest-cxf/target/classes">
+    </dir>
     <dir name="${basedir}/../../ext/scimv2/scim-rest-api/target/classes">
     </dir>
     <dir name="${basedir}/../../ext/scimv2/scim-rest-cxf/target/classes">


[5/6] syncope git commit: [SYNCOPE-152] SCIM configuration including attribute mapping + console extension

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java
new file mode 100644
index 0000000..e3b3140
--- /dev/null
+++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java
@@ -0,0 +1,397 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.logic;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.EntityTOUtils;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.scim.SCIMComplexConf;
+import org.apache.syncope.common.lib.scim.SCIMConf;
+import org.apache.syncope.common.lib.scim.SCIMUserAddressConf;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.core.logic.scim.SCIMConfManager;
+import org.apache.syncope.core.persistence.api.dao.AnyDAO;
+import org.apache.syncope.core.persistence.api.dao.search.MembershipCond;
+import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.core.spring.security.AuthDataAccessor;
+import org.apache.syncope.core.spring.security.SyncopeGrantedAuthority;
+import org.apache.syncope.ext.scimv2.api.data.Value;
+import org.apache.syncope.ext.scimv2.api.data.Group;
+import org.apache.syncope.ext.scimv2.api.data.Member;
+import org.apache.syncope.ext.scimv2.api.data.Meta;
+import org.apache.syncope.ext.scimv2.api.data.SCIMComplexValue;
+import org.apache.syncope.ext.scimv2.api.data.SCIMEnterpriseInfo;
+import org.apache.syncope.ext.scimv2.api.data.SCIMGroup;
+import org.apache.syncope.ext.scimv2.api.data.SCIMUser;
+import org.apache.syncope.ext.scimv2.api.data.SCIMUserAddress;
+import org.apache.syncope.ext.scimv2.api.data.SCIMUserManager;
+import org.apache.syncope.ext.scimv2.api.data.SCIMUserName;
+import org.apache.syncope.ext.scimv2.api.type.Function;
+import org.apache.syncope.ext.scimv2.api.type.Resource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SCIMDataBinder {
+
+    protected static final Logger LOG = LoggerFactory.getLogger(SCIMDataBinder.class);
+
+    @Autowired
+    private SCIMConfManager confManager;
+
+    @Autowired
+    private UserLogic userLogic;
+
+    @Autowired
+    private AuthDataAccessor authDataAccessor;
+
+    private <E extends Enum<?>> void fill(
+            final Map<String, AttrTO> attrs,
+            final List<SCIMComplexConf<E>> confs,
+            final List<SCIMComplexValue> values) {
+
+        for (SCIMComplexConf<?> conf : confs) {
+            SCIMComplexValue value = new SCIMComplexValue();
+
+            if (conf.getValue() != null && attrs.containsKey(conf.getValue())) {
+                value.setValue(attrs.get(conf.getValue()).getValues().get(0));
+            }
+            if (conf.getDisplay() != null && attrs.containsKey(conf.getDisplay())) {
+                value.setDisplay(attrs.get(conf.getDisplay()).getValues().get(0));
+            }
+            if (conf.getType() != null) {
+                value.setType(conf.getType().name());
+            }
+            if (conf.isPrimary()) {
+                value.setPrimary(true);
+            }
+
+            if (!value.isEmpty()) {
+                values.add(value);
+            }
+        }
+    }
+
+    public SCIMUser toSCIMUser(final UserTO userTO, final String location) {
+        SCIMConf conf = confManager.get();
+
+        SCIMUser user = new SCIMUser(
+                userTO.getKey(),
+                Collections.singletonList(Resource.User.schema()),
+                new Meta(
+                        Resource.User,
+                        userTO.getCreationDate(),
+                        userTO.getLastChangeDate() == null
+                        ? userTO.getCreationDate() : userTO.getLastChangeDate(),
+                        userTO.getETagValue(),
+                        location),
+                userTO.getUsername(),
+                !userTO.isSuspended());
+
+        Map<String, AttrTO> attrs = new HashMap<>();
+        attrs.putAll(EntityTOUtils.buildAttrMap(userTO.getPlainAttrs()));
+        attrs.putAll(EntityTOUtils.buildAttrMap(userTO.getDerAttrs()));
+        attrs.putAll(EntityTOUtils.buildAttrMap(userTO.getVirAttrs()));
+
+        if (conf.getUserConf() != null) {
+            if (conf.getUserConf().getName() != null) {
+                SCIMUserName name = new SCIMUserName();
+
+                if (conf.getUserConf().getName().getFamilyName() != null
+                        && attrs.containsKey(conf.getUserConf().getName().getFamilyName())) {
+
+                    name.setFamilyName(attrs.get(conf.getUserConf().getName().getFamilyName()).getValues().get(0));
+                }
+                if (conf.getUserConf().getName().getFormatted() != null
+                        && attrs.containsKey(conf.getUserConf().getName().getFormatted())) {
+
+                    name.setFormatted(attrs.get(conf.getUserConf().getName().getFormatted()).getValues().get(0));
+                }
+                if (conf.getUserConf().getName().getGivenName() != null
+                        && attrs.containsKey(conf.getUserConf().getName().getGivenName())) {
+
+                    name.setGivenName(attrs.get(conf.getUserConf().getName().getGivenName()).getValues().get(0));
+                }
+                if (conf.getUserConf().getName().getHonorificPrefix() != null
+                        && attrs.containsKey(conf.getUserConf().getName().getHonorificPrefix())) {
+
+                    name.setHonorificPrefix(
+                            attrs.get(conf.getUserConf().getName().getHonorificPrefix()).getValues().get(0));
+                }
+                if (conf.getUserConf().getName().getHonorificSuffix() != null
+                        && attrs.containsKey(conf.getUserConf().getName().getHonorificSuffix())) {
+
+                    name.setHonorificSuffix(
+                            attrs.get(conf.getUserConf().getName().getHonorificSuffix()).getValues().get(0));
+                }
+                if (conf.getUserConf().getName().getMiddleName() != null
+                        && attrs.containsKey(conf.getUserConf().getName().getMiddleName())) {
+
+                    name.setMiddleName(attrs.get(conf.getUserConf().getName().getMiddleName()).getValues().get(0));
+                }
+
+                if (!name.isEmpty()) {
+                    user.setName(name);
+                }
+            }
+
+            if (conf.getUserConf().getDisplayName() != null
+                    && attrs.containsKey(conf.getUserConf().getDisplayName())) {
+
+                user.setDisplayName(attrs.get(conf.getUserConf().getDisplayName()).getValues().get(0));
+            }
+
+            if (conf.getUserConf().getNickName() != null
+                    && attrs.containsKey(conf.getUserConf().getNickName())) {
+
+                user.setNickName(attrs.get(conf.getUserConf().getNickName()).getValues().get(0));
+            }
+
+            if (conf.getUserConf().getProfileUrl() != null
+                    && attrs.containsKey(conf.getUserConf().getProfileUrl())) {
+
+                user.setProfileUrl(attrs.get(conf.getUserConf().getProfileUrl()).getValues().get(0));
+            }
+
+            if (conf.getUserConf().getTitle() != null
+                    && attrs.containsKey(conf.getUserConf().getTitle())) {
+
+                user.setTitle(attrs.get(conf.getUserConf().getTitle()).getValues().get(0));
+            }
+
+            if (conf.getUserConf().getUserType() != null
+                    && attrs.containsKey(conf.getUserConf().getUserType())) {
+
+                user.setUserType(attrs.get(conf.getUserConf().getUserType()).getValues().get(0));
+            }
+
+            if (conf.getUserConf().getPreferredLanguage() != null
+                    && attrs.containsKey(conf.getUserConf().getPreferredLanguage())) {
+
+                user.setPreferredLanguage(attrs.get(conf.getUserConf().getPreferredLanguage()).getValues().get(0));
+            }
+
+            if (conf.getUserConf().getLocale() != null
+                    && attrs.containsKey(conf.getUserConf().getLocale())) {
+
+                user.setLocale(attrs.get(conf.getUserConf().getLocale()).getValues().get(0));
+            }
+
+            if (conf.getUserConf().getTimezone() != null
+                    && attrs.containsKey(conf.getUserConf().getTimezone())) {
+
+                user.setTimezone(attrs.get(conf.getUserConf().getTimezone()).getValues().get(0));
+            }
+
+            fill(attrs, conf.getUserConf().getEmails(), user.getEmails());
+            fill(attrs, conf.getUserConf().getPhoneNumbers(), user.getPhoneNumbers());
+            fill(attrs, conf.getUserConf().getIms(), user.getIms());
+            fill(attrs, conf.getUserConf().getPhotos(), user.getPhotos());
+            for (SCIMUserAddressConf addressConf : conf.getUserConf().getAddresses()) {
+                SCIMUserAddress address = new SCIMUserAddress();
+
+                if (addressConf.getFormatted() != null && attrs.containsKey(addressConf.getFormatted())) {
+                    address.setFormatted(attrs.get(addressConf.getFormatted()).getValues().get(0));
+                }
+                if (addressConf.getStreetAddress() != null && attrs.containsKey(addressConf.getStreetAddress())) {
+                    address.setStreetAddress(attrs.get(addressConf.getStreetAddress()).getValues().get(0));
+                }
+                if (addressConf.getLocality() != null && attrs.containsKey(addressConf.getLocality())) {
+                    address.setLocality(attrs.get(addressConf.getLocality()).getValues().get(0));
+                }
+                if (addressConf.getRegion() != null && attrs.containsKey(addressConf.getRegion())) {
+                    address.setRegion(attrs.get(addressConf.getRegion()).getValues().get(0));
+                }
+                if (addressConf.getCountry() != null && attrs.containsKey(addressConf.getCountry())) {
+                    address.setCountry(attrs.get(addressConf.getCountry()).getValues().get(0));
+                }
+                if (addressConf.getType() != null) {
+                    address.setType(addressConf.getType().name());
+                }
+                if (addressConf.isPrimary()) {
+                    address.setPrimary(true);
+                }
+
+                if (!address.isEmpty()) {
+                    user.getAddresses().add(address);
+                }
+            }
+
+            for (String certificate : conf.getUserConf().getX509Certificates()) {
+                if (attrs.containsKey(certificate)) {
+                    user.getX509Certificates().add(new Value(attrs.get(certificate).getValues().get(0)));
+                }
+            }
+        }
+
+        if (conf.getEnterpriseUserConf() != null) {
+            SCIMEnterpriseInfo enterpriseInfo = new SCIMEnterpriseInfo();
+
+            if (conf.getEnterpriseUserConf().getEmployeeNumber() != null
+                    && attrs.containsKey(conf.getEnterpriseUserConf().getEmployeeNumber())) {
+
+                enterpriseInfo.setEmployeeNumber(
+                        attrs.get(conf.getEnterpriseUserConf().getEmployeeNumber()).getValues().get(0));
+            }
+            if (conf.getEnterpriseUserConf().getCostCenter() != null
+                    && attrs.containsKey(conf.getEnterpriseUserConf().getCostCenter())) {
+
+                enterpriseInfo.setCostCenter(
+                        attrs.get(conf.getEnterpriseUserConf().getCostCenter()).getValues().get(0));
+            }
+            if (conf.getEnterpriseUserConf().getOrganization() != null
+                    && attrs.containsKey(conf.getEnterpriseUserConf().getOrganization())) {
+
+                enterpriseInfo.setOrganization(
+                        attrs.get(conf.getEnterpriseUserConf().getOrganization()).getValues().get(0));
+            }
+            if (conf.getEnterpriseUserConf().getDivision() != null
+                    && attrs.containsKey(conf.getEnterpriseUserConf().getDivision())) {
+
+                enterpriseInfo.setDivision(
+                        attrs.get(conf.getEnterpriseUserConf().getDivision()).getValues().get(0));
+            }
+            if (conf.getEnterpriseUserConf().getDepartment() != null
+                    && attrs.containsKey(conf.getEnterpriseUserConf().getDepartment())) {
+
+                enterpriseInfo.setDepartment(
+                        attrs.get(conf.getEnterpriseUserConf().getDepartment()).getValues().get(0));
+            }
+            if (conf.getEnterpriseUserConf().getManager() != null) {
+                SCIMUserManager manager = new SCIMUserManager();
+
+                if (conf.getEnterpriseUserConf().getManager().getManager() != null
+                        && attrs.containsKey(conf.getEnterpriseUserConf().getManager().getManager())) {
+
+                    try {
+                        UserTO userManager = userLogic.read(
+                                attrs.get(conf.getEnterpriseUserConf().getManager().getManager()).getValues().get(0));
+                        manager.setValue(userManager.getKey());
+                        manager.setRef(
+                                StringUtils.substringBefore(location, "/Users") + "/Users/" + userManager.getKey());
+
+                        if (conf.getEnterpriseUserConf().getManager().getDisplayName() != null) {
+                            AttrTO displayName = userManager.getPlainAttr(
+                                    conf.getEnterpriseUserConf().getManager().getDisplayName());
+                            if (displayName == null) {
+                                displayName = userManager.getDerAttr(
+                                        conf.getEnterpriseUserConf().getManager().getDisplayName());
+                            }
+                            if (displayName == null) {
+                                displayName = userManager.getVirAttr(
+                                        conf.getEnterpriseUserConf().getManager().getDisplayName());
+                            }
+                            if (displayName != null) {
+                                manager.setDisplayName(displayName.getValues().get(0));
+                            }
+                        }
+                    } catch (Exception e) {
+                        LOG.error("Could not read attribute {}",
+                                conf.getEnterpriseUserConf().getManager().getManager(), e);
+                    }
+                }
+
+                if (!manager.isEmpty()) {
+                    enterpriseInfo.setManager(manager);
+                }
+            }
+
+            if (!enterpriseInfo.isEmpty()) {
+                user.setEnterpriseInfo(enterpriseInfo);
+            }
+        }
+
+        for (MembershipTO membership : userTO.getMemberships()) {
+            user.getGroups().add(new Group(
+                    membership.getGroupKey(),
+                    StringUtils.substringBefore(location, "/Users") + "/Groups/" + membership.getGroupKey(),
+                    membership.getGroupName(),
+                    Function.direct));
+        }
+        for (MembershipTO membership : userTO.getDynMemberships()) {
+            user.getGroups().add(new Group(
+                    membership.getGroupKey(),
+                    StringUtils.substringBefore(location, "/Users") + "/Groups/" + membership.getGroupKey(),
+                    membership.getGroupName(),
+                    Function.indirect));
+        }
+
+        for (SyncopeGrantedAuthority authority : authDataAccessor.getAuthorities(userTO.getUsername())) {
+            user.getEntitlements().add(new Value(authority.getAuthority() + " on Realm(s) " + authority.getRealms()));
+        }
+
+        for (String role : userTO.getRoles()) {
+            user.getRoles().add(new Value(role));
+        }
+
+        return user;
+    }
+
+    public SCIMGroup toSCIMGroup(final GroupTO groupTO, final String location) {
+        SCIMGroup group = new SCIMGroup(
+                groupTO.getKey(),
+                Collections.singletonList(Resource.Group.schema()),
+                new Meta(
+                        Resource.Group,
+                        groupTO.getCreationDate(),
+                        groupTO.getLastChangeDate() == null
+                        ? groupTO.getCreationDate() : groupTO.getLastChangeDate(),
+                        groupTO.getETagValue(),
+                        location),
+                groupTO.getName());
+
+        MembershipCond membCond = new MembershipCond();
+        membCond.setGroup(groupTO.getKey());
+        SearchCond searchCond = SearchCond.getLeafCond(membCond);
+
+        int count = userLogic.
+                search(searchCond, 1, 1, Collections.<OrderByClause>emptyList(), SyncopeConstants.ROOT_REALM, false).
+                getLeft();
+
+        for (int page = 1; page <= (count / AnyDAO.DEFAULT_PAGE_SIZE) + 1; page++) {
+            List<UserTO> users = userLogic.search(
+                    searchCond,
+                    page,
+                    AnyDAO.DEFAULT_PAGE_SIZE,
+                    Collections.<OrderByClause>emptyList(),
+                    SyncopeConstants.ROOT_REALM,
+                    false).
+                    getRight();
+            for (UserTO userTO : users) {
+                group.getMembers().add(new Member(
+                        userTO.getKey(),
+                        StringUtils.substringBefore(location, "/Groups") + "/Users/" + userTO.getKey(),
+                        userTO.getUsername(),
+                        Resource.User));
+            }
+        }
+
+        return group;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMLogic.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMLogic.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMLogic.java
new file mode 100644
index 0000000..11085fb
--- /dev/null
+++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMLogic.java
@@ -0,0 +1,198 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.logic;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.core.UriBuilder;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+import org.apache.syncope.common.lib.scim.SCIMConf;
+import org.apache.syncope.core.logic.scim.SCIMConfManager;
+import org.apache.syncope.ext.scimv2.api.data.AuthenticationScheme;
+import org.apache.syncope.ext.scimv2.api.data.BulkConfigurationOption;
+import org.apache.syncope.ext.scimv2.api.data.ConfigurationOption;
+import org.apache.syncope.ext.scimv2.api.data.FilterConfigurationOption;
+import org.apache.syncope.ext.scimv2.api.data.Meta;
+import org.apache.syncope.ext.scimv2.api.data.ResourceType;
+import org.apache.syncope.ext.scimv2.api.data.SchemaExtension;
+import org.apache.syncope.ext.scimv2.api.data.ServiceProviderConfig;
+import org.apache.syncope.ext.scimv2.api.type.Resource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SCIMLogic extends AbstractLogic<AbstractBaseBean> {
+
+    private static final String SCHEMAS_JSON = "schemas.json";
+
+    private static final Object MONITOR = new Object();
+
+    private static ServiceProviderConfig SERVICE_PROVIDER_CONFIG;
+
+    private static ResourceType USER;
+
+    private static ResourceType GROUP;
+
+    private static String SCHEMAS;
+
+    private static final Map<String, String> SCHEMA_MAP = new HashMap<>();
+
+    @Autowired
+    private SCIMConfManager confManager;
+
+    private void init() {
+        try {
+            ObjectMapper mapper = new ObjectMapper();
+            JsonNode tree = mapper.readTree(getClass().getResourceAsStream("/" + SCHEMAS_JSON));
+            if (!tree.isArray()) {
+                throw new IOException("JSON node is not a tree");
+            }
+
+            ArrayNode schemaArray = (ArrayNode) tree;
+            SCHEMAS = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(tree);
+
+            for (JsonNode schema : schemaArray) {
+                SCHEMA_MAP.put(schema.get("id").asText(), mapper.writeValueAsString(schema));
+            }
+        } catch (IOException e) {
+            LOG.error("Could not parse the default schema definitions", e);
+        }
+    }
+
+    @PreAuthorize("isAuthenticated()")
+    public ServiceProviderConfig serviceProviderConfig(final UriBuilder uriBuilder) {
+        synchronized (MONITOR) {
+            if (SCHEMAS == null) {
+                init();
+            }
+
+            if (SERVICE_PROVIDER_CONFIG == null) {
+                SCIMConf conf = confManager.get();
+
+                SERVICE_PROVIDER_CONFIG = new ServiceProviderConfig(
+                        new Meta(
+                                Resource.ServiceProviderConfig,
+                                conf.getCreationDate(),
+                                conf.getLastChangeDate(),
+                                conf.getETagValue(),
+                                uriBuilder.build().toASCIIString()),
+                        new ConfigurationOption(true),
+                        new BulkConfigurationOption(true, conf.getBulkMaxOperations(), conf.getBulkMaxPayloadSize()),
+                        new FilterConfigurationOption(true, conf.getFilterMaxResults()),
+                        new ConfigurationOption(true),
+                        new ConfigurationOption(true),
+                        new ConfigurationOption(true));
+                SERVICE_PROVIDER_CONFIG.getAuthenticationSchemes().add(new AuthenticationScheme(
+                        "JSON Web Token",
+                        "Apache Syncope JWT authentication",
+                        URI.create("http://www.rfc-editor.org/info/rfc6750"),
+                        URI.create("https://syncope.apache.org/docs/"
+                                + "reference-guide.html#rest-authentication-and-authorization"),
+                        "oauthbearertoken",
+                        true));
+                SERVICE_PROVIDER_CONFIG.getAuthenticationSchemes().add(new AuthenticationScheme(
+                        "HTTP Basic",
+                        "Apache Syncope HTTP Basic authentication",
+                        URI.create("http://www.rfc-editor.org/info/rfc2617"),
+                        URI.create("https://syncope.apache.org/docs/"
+                                + "reference-guide.html#rest-authentication-and-authorization"),
+                        "httpbasic",
+                        false));
+            }
+        }
+        return SERVICE_PROVIDER_CONFIG;
+    }
+
+    @PreAuthorize("isAuthenticated()")
+    public List<ResourceType> resourceTypes(final UriBuilder uriBuilder) {
+        synchronized (MONITOR) {
+            if (USER == null) {
+                USER = new ResourceType("User", "User", "/Users", "User Account", Resource.User.schema(),
+                        new Meta(Resource.ResourceType,
+                                null, null, null, uriBuilder.path("User").build().toASCIIString()));
+                USER.getSchemaExtensions().add(new SchemaExtension(Resource.EnterpriseUser.schema(), true));
+            }
+            if (GROUP == null) {
+                GROUP = new ResourceType("Group", "Group", "/Groups", "Group", Resource.Group.schema(),
+                        new Meta(Resource.ResourceType,
+                                null, null, null, uriBuilder.path("Group").build().toASCIIString()));
+            }
+        }
+
+        return Arrays.asList(USER, GROUP);
+    }
+
+    @PreAuthorize("isAuthenticated()")
+    public ResourceType resourceType(final UriBuilder uriBuilder, final String type) {
+        if (Resource.User.name().equals(type)) {
+            resourceTypes(uriBuilder);
+            return USER;
+        } else if (Resource.Group.name().equals(type)) {
+            resourceTypes(uriBuilder);
+            return GROUP;
+        } else {
+            throw new IllegalArgumentException("Unsupported resource type: " + type);
+        }
+    }
+
+    @PreAuthorize("isAuthenticated()")
+    public String schemas() {
+        synchronized (MONITOR) {
+            if (SCHEMAS == null) {
+                init();
+            }
+        }
+
+        return SCHEMAS;
+    }
+
+    @PreAuthorize("isAuthenticated()")
+    public String schema(final String schema) {
+        synchronized (MONITOR) {
+            if (SCHEMAS == null) {
+                init();
+            }
+        }
+
+        String found = SCHEMA_MAP.get(schema);
+        if (found == null) {
+            throw new NotFoundException("Schema " + schema);
+        }
+
+        return found;
+    }
+
+    @Override
+    protected AbstractBaseBean resolveReference(final Method method, final Object... args)
+            throws UnresolvedReferenceException {
+
+        throw new UnresolvedReferenceException();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java
index 894ba24..a5a1733 100644
--- a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java
+++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java
@@ -18,39 +18,14 @@
  */
 package org.apache.syncope.core.logic.init;
 
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.common.lib.PropertyUtils;
+import org.apache.syncope.common.lib.scim.types.SCIMEntitlement;
 import org.apache.syncope.core.persistence.api.SyncopeLoader;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
 import org.springframework.stereotype.Component;
 
 @Component
 public class SCIMLoader implements SyncopeLoader {
 
-    private static final Logger LOG = LoggerFactory.getLogger(SCIMLoader.class);
-
-    private static final String SCIMV2_LOGIC_PROPERTIES = "scimv2-logic.properties";
-
-    private static final String SCHEMAS = "schemas.json";
-
-    private int bulkMaxOperations = 0;
-
-    private int bulkMaxPayloadSize = 0;
-
-    private int filterMaxResults = 0;
-
-    private String schemas;
-
-    private final Map<String, String> schemaMap = new HashMap<>();
-
     @Override
     public Integer getPriority() {
         return 1000;
@@ -58,49 +33,7 @@ public class SCIMLoader implements SyncopeLoader {
 
     @Override
     public void load() {
-        Pair<Properties, String> init = PropertyUtils.read(getClass(), SCIMV2_LOGIC_PROPERTIES, "conf.directory");
-        Properties props = init.getLeft();
-
-        bulkMaxOperations = Integer.valueOf(props.getProperty("bulk.maxOperations"));
-        bulkMaxPayloadSize = Integer.valueOf(props.getProperty("bulk.maxPayloadSize"));
-        filterMaxResults = Integer.valueOf(props.getProperty("filter.maxResults"));
-
-        try {
-            ObjectMapper mapper = new ObjectMapper();
-            JsonNode tree = mapper.readTree(getClass().getResourceAsStream("/" + SCHEMAS));
-            if (!tree.isArray()) {
-                throw new IOException("JSON node is not a tree");
-            }
-
-            ArrayNode schemaArray = (ArrayNode) tree;
-            schemas = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(tree);
-
-            for (JsonNode schema : schemaArray) {
-                schemaMap.put(schema.get("id").asText(), mapper.writeValueAsString(schema));
-            }
-        } catch (IOException e) {
-            LOG.error("Could not parse the default schema definitions", e);
-        }
-    }
-
-    public int getBulkMaxOperations() {
-        return bulkMaxOperations;
-    }
-
-    public int getBulkMaxPayloadSize() {
-        return bulkMaxPayloadSize;
-    }
-
-    public int getFilterMaxResults() {
-        return filterMaxResults;
-    }
-
-    public String getSchemas() {
-        return schemas;
-    }
-
-    public String getSchema(final String schema) {
-        return schemaMap.get(schema);
+        EntitlementsHolder.getInstance().init(SCIMEntitlement.values());
     }
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMConfManager.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMConfManager.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMConfManager.java
new file mode 100644
index 0000000..ede870b
--- /dev/null
+++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMConfManager.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.logic.scim;
+
+import java.util.Date;
+import javax.ws.rs.core.MediaType;
+import org.apache.syncope.common.lib.scim.SCIMConf;
+import org.apache.syncope.common.lib.scim.types.SCIMEntitlement;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.PlainSchemaTO;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.core.logic.ConfigurationLogic;
+import org.apache.syncope.core.logic.SchemaLogic;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+import org.identityconnectors.common.Base64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SCIMConfManager {
+
+    protected static final Logger LOG = LoggerFactory.getLogger(SCIMConfManager.class);
+
+    @Autowired
+    private ConfigurationLogic configurationLogic;
+
+    @Autowired
+    private SchemaLogic schemaLogic;
+
+    @PreAuthorize("hasRole('" + SCIMEntitlement.SCIM_CONF_GET + "')")
+    public SCIMConf get() {
+        AttrTO confTO = null;
+        try {
+            confTO = configurationLogic.get(SCIMConf.KEY);
+        } catch (Exception e) {
+            LOG.error("{} not found, reverting to default", SCIMConf.KEY);
+        }
+
+        SCIMConf conf = null;
+        if (confTO != null) {
+            try {
+                conf = POJOHelper.deserialize(new String(Base64.decode(confTO.getValues().get(0))), SCIMConf.class);
+            } catch (Exception e) {
+                LOG.error("Could not deserialize, reverting to default", e);
+            }
+        }
+        if (conf == null) {
+            conf = new SCIMConf();
+            set(conf);
+        }
+
+        return conf;
+    }
+
+    @PreAuthorize("hasRole('" + SCIMEntitlement.SCIM_CONF_SET + "')")
+    public void set(final SCIMConf conf) {
+        try {
+            schemaLogic.read(SchemaType.PLAIN, SCIMConf.KEY);
+        } catch (NotFoundException e) {
+            PlainSchemaTO scimConf = new PlainSchemaTO();
+            scimConf.setKey(SCIMConf.KEY);
+            scimConf.setType(AttrSchemaType.Binary);
+            scimConf.setMimeType(MediaType.APPLICATION_JSON);
+            schemaLogic.create(SchemaType.PLAIN, scimConf);
+        }
+        conf.setLastChangeDate(new Date());
+
+        configurationLogic.set(new AttrTO.Builder().
+                schema(SCIMConf.KEY).value(Base64.encode(POJOHelper.serialize(conf).getBytes())).build());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/logic/src/main/resources/scimv2-logic.properties
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/resources/scimv2-logic.properties b/ext/scimv2/logic/src/main/resources/scimv2-logic.properties
deleted file mode 100644
index 2d85a37..0000000
--- a/ext/scimv2/logic/src/main/resources/scimv2-logic.properties
+++ /dev/null
@@ -1,21 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-conf.directory=${conf.directory}
-
-bulk.maxOperations=1000
-bulk.maxPayloadSize=1048576
-filter.maxResults=200

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/pom.xml
----------------------------------------------------------------------
diff --git a/ext/scimv2/pom.xml b/ext/scimv2/pom.xml
index 409f642..a04e6bd 100644
--- a/ext/scimv2/pom.xml
+++ b/ext/scimv2/pom.xml
@@ -38,9 +38,13 @@ under the License.
   </properties>
   
   <modules>
+    <module>common-lib</module>
+    <module>rest-api</module>
+    <module>rest-cxf</module>
     <module>scim-rest-api</module>
     <module>scim-rest-cxf</module>
     <module>logic</module>
+    <module>client-console</module>
   </modules>
 
 </project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/rest-api/pom.xml
----------------------------------------------------------------------
diff --git a/ext/scimv2/rest-api/pom.xml b/ext/scimv2/rest-api/pom.xml
new file mode 100644
index 0000000..b56ada6
--- /dev/null
+++ b/ext/scimv2/rest-api/pom.xml
@@ -0,0 +1,77 @@
+<?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.ext</groupId>
+    <artifactId>syncope-ext-scimv2</artifactId>
+    <version>2.0.7-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Ext: SCIMv2 REST API</name>
+  <description>Apache Syncope Ext: SCIMv2 REST API</description>
+  <groupId>org.apache.syncope.ext.scimv2</groupId>
+  <artifactId>syncope-ext-scimv2-rest-api</artifactId>
+  <packaging>jar</packaging>
+  
+  <properties>
+    <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.syncope.common</groupId>
+      <artifactId>syncope-common-rest-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-common-lib</artifactId>      
+      <version>${project.version}</version>
+    </dependency>    
+  </dependencies>
+
+  <build>
+    <plugins>
+      <!-- Generating javadoc JAR artifact for usage with CXF's WADL generator (for core) -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <inherited>true</inherited>
+        <executions>
+          <execution>
+            <id>attach-javadocs</id>
+            <goals>
+              <goal>jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SCIMConfService.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SCIMConfService.java b/ext/scimv2/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SCIMConfService.java
new file mode 100644
index 0000000..fdc4da3
--- /dev/null
+++ b/ext/scimv2/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SCIMConfService.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.rest.api.service;
+
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import org.apache.syncope.common.lib.scim.SCIMConf;
+
+/**
+ * REST operations for SCIM 2.0 configuration.
+ */
+@Path("scimv2conf")
+public interface SCIMConfService extends JAXRSService {
+
+    /**
+     * Reads SCIM configuration, generates empty if missing.
+     *
+     * @return SCIM configuration
+     */
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    SCIMConf get();
+
+    /**
+     * Sets SCIM configuration.
+     *
+     * @param conf SCIM configuration
+     */
+    @PUT
+    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    void set(@NotNull SCIMConf conf);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/rest-cxf/pom.xml
----------------------------------------------------------------------
diff --git a/ext/scimv2/rest-cxf/pom.xml b/ext/scimv2/rest-cxf/pom.xml
new file mode 100644
index 0000000..f829877
--- /dev/null
+++ b/ext/scimv2/rest-cxf/pom.xml
@@ -0,0 +1,72 @@
+<?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.ext</groupId>
+    <artifactId>syncope-ext-scimv2</artifactId>
+    <version>2.0.7-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Ext: SCIMv2 REST CXF</name>
+  <description>Apache Syncope Ext: SCIMv2 REST CXF</description>
+  <groupId>org.apache.syncope.ext.scimv2</groupId>
+  <artifactId>syncope-ext-scimv2-rest-cxf</artifactId>
+  <packaging>jar</packaging>
+  
+  <properties>
+    <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.syncope.core</groupId>
+      <artifactId>syncope-core-rest-cxf</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-rest-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-rest-api</artifactId>
+      <version>${project.version}</version>
+      <classifier>javadoc</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-logic</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SCIMConfServiceImpl.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SCIMConfServiceImpl.java b/ext/scimv2/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SCIMConfServiceImpl.java
new file mode 100644
index 0000000..223aca7
--- /dev/null
+++ b/ext/scimv2/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SCIMConfServiceImpl.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.core.rest.cxf.service;
+
+import org.apache.syncope.common.lib.scim.SCIMConf;
+import org.apache.syncope.common.rest.api.service.SCIMConfService;
+import org.apache.syncope.core.logic.scim.SCIMConfManager;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class SCIMConfServiceImpl extends AbstractServiceImpl implements SCIMConfService {
+
+    @Autowired
+    private SCIMConfManager manager;
+
+    @Override
+    public SCIMConf get() {
+        return manager.get();
+    }
+
+    @Override
+    public void set(final SCIMConf conf) {
+        manager.set(conf);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Display.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Display.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Display.java
deleted file mode 100644
index f79796c..0000000
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Display.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.ext.scimv2.api.data;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public class Display extends SCIMBean {
-
-    private static final long serialVersionUID = 5337055958765320091L;
-
-    private final String value;
-
-    private final String display;
-
-    @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
-    public Display(@JsonProperty("value") final String value, @JsonProperty("display") final String display) {
-        this.value = value;
-        this.display = display;
-    }
-
-    public String getValue() {
-        return value;
-    }
-
-    public String getDisplay() {
-        return display;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Reference.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Reference.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Reference.java
index d65f5e8..a00c793 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Reference.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Reference.java
@@ -20,18 +20,25 @@ package org.apache.syncope.ext.scimv2.api.data;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 
-abstract class Reference extends Display {
+abstract class Reference extends Value {
 
     private static final long serialVersionUID = -6190164044699376089L;
 
+    private final String display;
+
     @JsonProperty("$ref")
     private final String ref;
 
     Reference(final String value, final String display, final String ref) {
-        super(value, display);
+        super(value);
+        this.display = display;
         this.ref = ref;
     }
 
+    public String getDisplay() {
+        return display;
+    }
+
     public String getRef() {
         return ref;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMBean.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMBean.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMBean.java
index 95334cf..ca191be 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMBean.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMBean.java
@@ -21,7 +21,7 @@ package org.apache.syncope.ext.scimv2.api.data;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import java.io.Serializable;
 
-@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
 abstract class SCIMBean implements Serializable {
 
     private static final long serialVersionUID = 7604407251038024743L;

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMComplexValue.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMComplexValue.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMComplexValue.java
new file mode 100644
index 0000000..94c4320
--- /dev/null
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMComplexValue.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.ext.scimv2.api.data;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+public class SCIMComplexValue extends SCIMBean {
+
+    private static final long serialVersionUID = -3887211468327809832L;
+
+    private String value;
+
+    private String display;
+
+    private String type;
+
+    private boolean primary;
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(final String value) {
+        this.value = value;
+    }
+
+    public String getDisplay() {
+        return display;
+    }
+
+    public void setDisplay(final String display) {
+        this.display = display;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(final String type) {
+        this.type = type;
+    }
+
+    public boolean isPrimary() {
+        return primary;
+    }
+
+    public void setPrimary(final boolean primary) {
+        this.primary = primary;
+    }
+
+    @JsonIgnore
+    public boolean isEmpty() {
+        return value == null && display == null && type == null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMEnterpriseInfo.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMEnterpriseInfo.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMEnterpriseInfo.java
new file mode 100644
index 0000000..d419c09
--- /dev/null
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMEnterpriseInfo.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.ext.scimv2.api.data;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+public class SCIMEnterpriseInfo extends SCIMBean {
+
+    private static final long serialVersionUID = 5745005071861557082L;
+
+    private String employeeNumber;
+
+    private String costCenter;
+
+    private String organization;
+
+    private String division;
+
+    private String department;
+
+    private SCIMUserManager manager;
+
+    public String getEmployeeNumber() {
+        return employeeNumber;
+    }
+
+    public void setEmployeeNumber(final String employeeNumber) {
+        this.employeeNumber = employeeNumber;
+    }
+
+    public String getCostCenter() {
+        return costCenter;
+    }
+
+    public void setCostCenter(final String costCenter) {
+        this.costCenter = costCenter;
+    }
+
+    public String getOrganization() {
+        return organization;
+    }
+
+    public void setOrganization(final String organization) {
+        this.organization = organization;
+    }
+
+    public String getDivision() {
+        return division;
+    }
+
+    public void setDivision(final String division) {
+        this.division = division;
+    }
+
+    public String getDepartment() {
+        return department;
+    }
+
+    public void setDepartment(final String department) {
+        this.department = department;
+    }
+
+    public SCIMUserManager getManager() {
+        return manager;
+    }
+
+    public void setManager(final SCIMUserManager manager) {
+        this.manager = manager;
+    }
+
+    @JsonIgnore
+    public boolean isEmpty() {
+        return employeeNumber == null
+                && costCenter == null
+                && organization == null
+                && division == null
+                && department == null
+                && manager == null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUser.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUser.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUser.java
index c76c0f0..775b1ad 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUser.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUser.java
@@ -24,18 +24,61 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 import java.util.ArrayList;
 import java.util.List;
 
-@JsonPropertyOrder({ "schemas", "id", "externalId", "userName", "active", "groups", "roles", "meta" })
+@JsonPropertyOrder({ "schemas", "id", "externalId",
+    "userName", "password", "active",
+    "name", "displayName", "nickName", "profileUrl", "title", "userType", "preferredLanguage", "locale", "timezone",
+    "emails", "phoneNumbers", "ims", "photos", "addresses", "x509Certificates",
+    "groups", "entitlements", "roles",
+    "enterpriseInfo",
+    "meta" })
 public class SCIMUser extends SCIMResource {
 
     private static final long serialVersionUID = -2935466041674390279L;
 
     private final String userName;
 
+    private String password;
+
     private final boolean active;
 
+    private SCIMUserName name;
+
+    private String displayName;
+
+    private String nickName;
+
+    private String profileUrl;
+
+    private String title;
+
+    private String userType;
+
+    private String preferredLanguage;
+
+    private String locale;
+
+    private String timezone;
+
+    private final List<SCIMComplexValue> emails = new ArrayList<>();
+
+    private final List<SCIMComplexValue> phoneNumbers = new ArrayList<>();
+
+    private final List<SCIMComplexValue> ims = new ArrayList<>();
+
+    private final List<SCIMComplexValue> photos = new ArrayList<>();
+
+    private final List<SCIMUserAddress> addresses = new ArrayList<>();
+
+    private final List<Value> x509Certificates = new ArrayList<>();
+
     private final List<Group> groups = new ArrayList<>();
 
-    private final List<Display> roles = new ArrayList<>();
+    private final List<Value> entitlements = new ArrayList<>();
+
+    private final List<Value> roles = new ArrayList<>();
+
+    @JsonProperty("urn:ietf:params:scim:schemas:extension:enterprise:2.0:User")
+    private SCIMEnterpriseInfo enterpriseInfo;
 
     @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
     public SCIMUser(
@@ -54,16 +97,132 @@ public class SCIMUser extends SCIMResource {
         return userName;
     }
 
+    public void setPassword(final String password) {
+        this.password = password;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
     public boolean isActive() {
         return active;
     }
 
+    public SCIMUserName getName() {
+        return name;
+    }
+
+    public void setName(final SCIMUserName name) {
+        this.name = name;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public void setDisplayName(final String displayName) {
+        this.displayName = displayName;
+    }
+
+    public String getNickName() {
+        return nickName;
+    }
+
+    public void setNickName(final String nickName) {
+        this.nickName = nickName;
+    }
+
+    public String getProfileUrl() {
+        return profileUrl;
+    }
+
+    public void setProfileUrl(final String profileUrl) {
+        this.profileUrl = profileUrl;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(final String title) {
+        this.title = title;
+    }
+
+    public String getUserType() {
+        return userType;
+    }
+
+    public void setUserType(final String userType) {
+        this.userType = userType;
+    }
+
+    public String getPreferredLanguage() {
+        return preferredLanguage;
+    }
+
+    public void setPreferredLanguage(final String preferredLanguage) {
+        this.preferredLanguage = preferredLanguage;
+    }
+
+    public String getLocale() {
+        return locale;
+    }
+
+    public void setLocale(final String locale) {
+        this.locale = locale;
+    }
+
+    public String getTimezone() {
+        return timezone;
+    }
+
+    public void setTimezone(final String timezone) {
+        this.timezone = timezone;
+    }
+
+    public List<SCIMComplexValue> getEmails() {
+        return emails;
+    }
+
+    public List<SCIMComplexValue> getPhoneNumbers() {
+        return phoneNumbers;
+    }
+
+    public List<SCIMComplexValue> getIms() {
+        return ims;
+    }
+
+    public List<SCIMComplexValue> getPhotos() {
+        return photos;
+    }
+
+    public List<SCIMUserAddress> getAddresses() {
+        return addresses;
+    }
+
+    public List<Value> getX509Certificates() {
+        return x509Certificates;
+    }
+
     public List<Group> getGroups() {
         return groups;
     }
 
-    public List<Display> getRoles() {
+    public List<Value> getEntitlements() {
+        return entitlements;
+    }
+
+    public List<Value> getRoles() {
         return roles;
     }
 
+    public SCIMEnterpriseInfo getEnterpriseInfo() {
+        return enterpriseInfo;
+    }
+
+    public void setEnterpriseInfo(final SCIMEnterpriseInfo enterpriseInfo) {
+        this.enterpriseInfo = enterpriseInfo;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserAddress.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserAddress.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserAddress.java
new file mode 100644
index 0000000..3c1f0d9
--- /dev/null
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserAddress.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.ext.scimv2.api.data;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+public class SCIMUserAddress extends SCIMBean {
+
+    private static final long serialVersionUID = -7936040729842689890L;
+
+    private String formatted;
+
+    private String streetAddress;
+
+    private String locality;
+
+    private String region;
+
+    private String postalCode;
+
+    private String country;
+
+    private String type;
+
+    private boolean primary;
+
+    public String getFormatted() {
+        return formatted;
+    }
+
+    public void setFormatted(final String formatted) {
+        this.formatted = formatted;
+    }
+
+    public String getStreetAddress() {
+        return streetAddress;
+    }
+
+    public void setStreetAddress(final String streetAddress) {
+        this.streetAddress = streetAddress;
+    }
+
+    public String getLocality() {
+        return locality;
+    }
+
+    public void setLocality(final String locality) {
+        this.locality = locality;
+    }
+
+    public String getRegion() {
+        return region;
+    }
+
+    public void setRegion(final String region) {
+        this.region = region;
+    }
+
+    public String getPostalCode() {
+        return postalCode;
+    }
+
+    public void setPostalCode(final String postalCode) {
+        this.postalCode = postalCode;
+    }
+
+    public String getCountry() {
+        return country;
+    }
+
+    public void setCountry(final String country) {
+        this.country = country;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(final String type) {
+        this.type = type;
+    }
+
+    public boolean isPrimary() {
+        return primary;
+    }
+
+    public void setPrimary(final boolean primary) {
+        this.primary = primary;
+    }
+
+    @JsonIgnore
+    public boolean isEmpty() {
+        return formatted == null
+                && streetAddress == null
+                && locality == null
+                && region == null
+                && postalCode == null
+                && country == null
+                && type == null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserManager.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserManager.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserManager.java
new file mode 100644
index 0000000..c1294e9
--- /dev/null
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserManager.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.ext.scimv2.api.data;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class SCIMUserManager extends SCIMBean {
+
+    private static final long serialVersionUID = -4193118676994783252L;
+
+    private String value;
+
+    @JsonProperty("$ref")
+    private String ref;
+
+    private String displayName;
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(final String value) {
+        this.value = value;
+    }
+
+    public String getRef() {
+        return ref;
+    }
+
+    public void setRef(final String ref) {
+        this.ref = ref;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public void setDisplayName(final String displayName) {
+        this.displayName = displayName;
+    }
+
+    @JsonIgnore
+    public boolean isEmpty() {
+        return value == null && ref == null && displayName == null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserName.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserName.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserName.java
new file mode 100644
index 0000000..0293e95
--- /dev/null
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserName.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.ext.scimv2.api.data;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+public class SCIMUserName extends SCIMBean {
+
+    private static final long serialVersionUID = 5492302691746462480L;
+
+    private String formatted;
+
+    private String familyName;
+
+    private String givenName;
+
+    private String middleName;
+
+    private String honorificPrefix;
+
+    private String honorificSuffix;
+
+    public String getFormatted() {
+        return formatted;
+    }
+
+    public void setFormatted(final String formatted) {
+        this.formatted = formatted;
+    }
+
+    public String getFamilyName() {
+        return familyName;
+    }
+
+    public void setFamilyName(final String familyName) {
+        this.familyName = familyName;
+    }
+
+    public String getGivenName() {
+        return givenName;
+    }
+
+    public void setGivenName(final String givenName) {
+        this.givenName = givenName;
+    }
+
+    public String getMiddleName() {
+        return middleName;
+    }
+
+    public void setMiddleName(final String middleName) {
+        this.middleName = middleName;
+    }
+
+    public String getHonorificPrefix() {
+        return honorificPrefix;
+    }
+
+    public void setHonorificPrefix(final String honorificPrefix) {
+        this.honorificPrefix = honorificPrefix;
+    }
+
+    public String getHonorificSuffix() {
+        return honorificSuffix;
+    }
+
+    public void setHonorificSuffix(final String honorificSuffix) {
+        this.honorificSuffix = honorificSuffix;
+    }
+
+    @JsonIgnore
+    public boolean isEmpty() {
+        return formatted == null
+                && familyName == null
+                && givenName == null
+                && middleName == null
+                && honorificPrefix == null
+                && honorificSuffix == null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/ServiceProviderConfig.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/ServiceProviderConfig.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/ServiceProviderConfig.java
index 3014a6c..75eec0a 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/ServiceProviderConfig.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/ServiceProviderConfig.java
@@ -20,17 +20,22 @@ package org.apache.syncope.ext.scimv2.api.data;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import org.apache.syncope.ext.scimv2.api.type.Resource;
 
+@JsonPropertyOrder(
+        { "schemas", "patch", "bulk", "filter", "changePassword", "sort", "etag", "authenticationSchemes", "meta" })
 public class ServiceProviderConfig extends SCIMBean {
 
     private static final long serialVersionUID = 1027738509789460252L;
 
     private final List<String> schemas = Arrays.asList(Resource.ServiceProviderConfig.schema());
 
+    private final Meta meta;
+
     private final ConfigurationOption patch;
 
     private final BulkConfigurationOption bulk;
@@ -47,6 +52,7 @@ public class ServiceProviderConfig extends SCIMBean {
 
     @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
     public ServiceProviderConfig(
+            @JsonProperty("meta") final Meta meta,
             @JsonProperty("patch") final ConfigurationOption patch,
             @JsonProperty("bulk") final BulkConfigurationOption bulk,
             @JsonProperty("filter") final FilterConfigurationOption filter,
@@ -54,6 +60,7 @@ public class ServiceProviderConfig extends SCIMBean {
             @JsonProperty("sort") final ConfigurationOption sort,
             @JsonProperty("etag") final ConfigurationOption etag) {
 
+        this.meta = meta;
         this.patch = patch;
         this.bulk = bulk;
         this.filter = filter;
@@ -66,6 +73,10 @@ public class ServiceProviderConfig extends SCIMBean {
         return schemas;
     }
 
+    public Meta getMeta() {
+        return meta;
+    }
+
     public ConfigurationOption getPatch() {
         return patch;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Value.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Value.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Value.java
new file mode 100644
index 0000000..543f000
--- /dev/null
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Value.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.ext.scimv2.api.data;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Value extends SCIMBean {
+
+    private static final long serialVersionUID = 5337055958765320091L;
+
+    private final String value;
+
+    @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+    public Value(@JsonProperty("value") final String value) {
+        this.value = value;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/GroupService.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/GroupService.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/GroupService.java
index 8881ec8..196572e 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/GroupService.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/GroupService.java
@@ -33,7 +33,7 @@ import org.apache.syncope.ext.scimv2.api.SCIMConstants;
 import org.apache.syncope.ext.scimv2.api.data.SCIMGroup;
 
 @Path("v2/Groups")
-public interface GroupService extends SCIMService<SCIMGroup> {
+public interface GroupService extends SearchService<SCIMGroup> {
 
     @POST
     @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/RootService.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/RootService.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/RootService.java
deleted file mode 100644
index 6e9b201..0000000
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/RootService.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.ext.scimv2.api.service;
-
-import java.util.List;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Response;
-import org.apache.syncope.ext.scimv2.api.SCIMConstants;
-import org.apache.syncope.ext.scimv2.api.data.ResourceType;
-import org.apache.syncope.ext.scimv2.api.data.SCIMResource;
-import org.apache.syncope.ext.scimv2.api.data.ServiceProviderConfig;
-
-@Path("v2")
-public interface RootService extends SCIMService<SCIMResource> {
-
-    @GET
-    @Path("ServiceProviderConfig")
-    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
-    ServiceProviderConfig serviceProviderConfig();
-
-    @GET
-    @Path("ResourceTypes")
-    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
-    List<ResourceType> resourceTypes();
-
-    @GET
-    @Path("ResourceTypes/{type}")
-    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
-    ResourceType resourceType(@PathParam("type") String type);
-
-    @GET
-    @Path("Schemas")
-    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
-    Response schemas();
-
-    @GET
-    @Path("Schemas/{schema}")
-    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
-    Response schema(@PathParam("schema") String schema);
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SCIMService.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SCIMService.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SCIMService.java
index 1b2fd3f..6064747 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SCIMService.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SCIMService.java
@@ -20,22 +20,40 @@ package org.apache.syncope.ext.scimv2.api.service;
 
 import java.util.List;
 import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
 import org.apache.syncope.ext.scimv2.api.SCIMConstants;
-import org.apache.syncope.ext.scimv2.api.data.ListResponse;
+import org.apache.syncope.ext.scimv2.api.data.ResourceType;
 import org.apache.syncope.ext.scimv2.api.data.SCIMResource;
-import org.apache.syncope.ext.scimv2.api.type.SortOrder;
+import org.apache.syncope.ext.scimv2.api.data.ServiceProviderConfig;
 
-public interface SCIMService<R extends SCIMResource> {
+@Path("v2")
+public interface SCIMService extends SearchService<SCIMResource> {
 
     @GET
+    @Path("ServiceProviderConfig")
     @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
-    ListResponse<R> search(
-            @QueryParam("startIndex") Integer startIndex,
-            @QueryParam("count") Integer count,
-            @QueryParam("filter") String filter,
-            @QueryParam("sortBy") String sortBy,
-            @QueryParam("sortOrder") SortOrder sortOrder,
-            @QueryParam("attributes") List<String> attributes);
+    ServiceProviderConfig serviceProviderConfig();
+
+    @GET
+    @Path("ResourceTypes")
+    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
+    List<ResourceType> resourceTypes();
+
+    @GET
+    @Path("ResourceTypes/{type}")
+    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
+    ResourceType resourceType(@PathParam("type") String type);
+
+    @GET
+    @Path("Schemas")
+    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
+    Response schemas();
+
+    @GET
+    @Path("Schemas/{schema}")
+    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
+    Response schema(@PathParam("schema") String schema);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SearchService.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SearchService.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SearchService.java
new file mode 100644
index 0000000..fcd4789
--- /dev/null
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SearchService.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.ext.scimv2.api.service;
+
+import java.util.List;
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import org.apache.syncope.ext.scimv2.api.SCIMConstants;
+import org.apache.syncope.ext.scimv2.api.data.ListResponse;
+import org.apache.syncope.ext.scimv2.api.data.SCIMResource;
+import org.apache.syncope.ext.scimv2.api.type.SortOrder;
+
+public interface SearchService<R extends SCIMResource> {
+
+    @GET
+    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
+    ListResponse<R> search(
+            @QueryParam("startIndex") Integer startIndex,
+            @QueryParam("count") Integer count,
+            @QueryParam("filter") String filter,
+            @QueryParam("sortBy") String sortBy,
+            @QueryParam("sortOrder") SortOrder sortOrder,
+            @QueryParam("attributes") List<String> attributes);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/UserService.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/UserService.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/UserService.java
index 8003b66..1135650 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/UserService.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/UserService.java
@@ -33,7 +33,7 @@ import org.apache.syncope.ext.scimv2.api.SCIMConstants;
 import org.apache.syncope.ext.scimv2.api.data.SCIMUser;
 
 @Path("v2/Users")
-public interface UserService extends SCIMService<SCIMUser> {
+public interface UserService extends SearchService<SCIMUser> {
 
     @POST
     @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/AddETagFilter.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/AddETagFilter.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/AddETagFilter.java
index 498ea95..d2c76a8 100644
--- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/AddETagFilter.java
+++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/AddETagFilter.java
@@ -46,7 +46,7 @@ public class AddETagFilter implements ContainerResponseFilter {
                 if (lastModified != null) {
                     String etagValue = String.valueOf(lastModified.getTime());
                     if (StringUtils.isNotBlank(etagValue)) {
-                        resCtx.getHeaders().add(HttpHeaders.ETAG, new EntityTag(etagValue).toString());
+                        resCtx.getHeaders().add(HttpHeaders.ETAG, new EntityTag(etagValue, true).toString());
                     }
                 }
             }


[3/6] syncope git commit: [SYNCOPE-152] SCIM configuration including attribute mapping + console extension

Posted by il...@apache.org.
[SYNCOPE-152] SCIM configuration including attribute mapping + console extension


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

Branch: refs/heads/master
Commit: 7cd228925e538bd7743a22ac923bdee4b30a32e6
Parents: e3ac899
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Tue Nov 14 16:54:25 2017 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Tue Nov 14 17:23:18 2017 +0100

----------------------------------------------------------------------
 .../archetype-resources/console/pom.xml         |   6 +
 .../resources/archetype-resources/core/pom.xml  |  11 +
 .../panels/ParametersDirectoryPanel.java        |   2 +-
 .../console/panels/RoleDirectoryPanel.java      |   2 +-
 ext/scimv2/client-console/pom.xml               |  78 ++++
 .../syncope/client/console/pages/SCIMConf.java  | 137 +++++++
 .../client/console/rest/SCIMConfRestClient.java |  35 ++
 .../syncope/client/console/pages/SCIMConf.html  |  41 ++
 .../client/console/pages/SCIMConf.properties    |  17 +
 .../client/console/pages/SCIMConf_it.properties |  17 +
 .../console/pages/SCIMConf_pt_BR.properties     |  17 +
 .../client/console/pages/SCIMConf_ru.properties |  17 +
 ext/scimv2/common-lib/pom.xml                   |  56 +++
 .../common/lib/scim/SCIMComplexConf.java        |  67 ++++
 .../syncope/common/lib/scim/SCIMConf.java       | 126 ++++++
 .../common/lib/scim/SCIMEnterpriseUserConf.java |  87 ++++
 .../common/lib/scim/SCIMManagerConf.java        |  47 +++
 .../common/lib/scim/SCIMUserAddressConf.java    | 107 +++++
 .../syncope/common/lib/scim/SCIMUserConf.java   | 159 ++++++++
 .../common/lib/scim/SCIMUserNameConf.java       |  87 ++++
 .../lib/scim/types/AddressCanonicalType.java    |  26 ++
 .../lib/scim/types/EmailCanonicalType.java      |  26 ++
 .../common/lib/scim/types/IMCanonicalType.java  |  31 ++
 .../scim/types/PhoneNumberCanonicalType.java    |  29 ++
 .../lib/scim/types/PhotoCanonicalType.java      |  25 ++
 .../common/lib/scim/types/SCIMEntitlement.java  |  52 +++
 ext/scimv2/logic/pom.xml                        |   6 +
 .../apache/syncope/core/logic/RootLogic.java    | 143 -------
 .../syncope/core/logic/SCIMDataBinder.java      | 394 +++++++++++++++++++
 .../apache/syncope/core/logic/SCIMLogic.java    | 198 ++++++++++
 .../syncope/core/logic/init/SCIMLoader.java     |  73 +---
 .../core/logic/scim/SCIMConfManager.java        |  93 +++++
 .../src/main/resources/scimv2-logic.properties  |  21 -
 ext/scimv2/pom.xml                              |   4 +
 ext/scimv2/rest-api/pom.xml                     |  77 ++++
 .../rest/api/service/SCIMConfService.java       |  53 +++
 ext/scimv2/rest-cxf/pom.xml                     |  72 ++++
 .../rest/cxf/service/SCIMConfServiceImpl.java   |  41 ++
 .../syncope/ext/scimv2/api/data/Display.java    |  46 ---
 .../syncope/ext/scimv2/api/data/Reference.java  |  11 +-
 .../syncope/ext/scimv2/api/data/SCIMBean.java   |   2 +-
 .../ext/scimv2/api/data/SCIMComplexValue.java   |  71 ++++
 .../ext/scimv2/api/data/SCIMEnterpriseInfo.java |  96 +++++
 .../syncope/ext/scimv2/api/data/SCIMUser.java   | 165 +++++++-
 .../ext/scimv2/api/data/SCIMUserAddress.java    | 117 ++++++
 .../ext/scimv2/api/data/SCIMUserManager.java    |  63 +++
 .../ext/scimv2/api/data/SCIMUserName.java       |  96 +++++
 .../scimv2/api/data/ServiceProviderConfig.java  |  11 +
 .../syncope/ext/scimv2/api/data/Value.java      |  39 ++
 .../ext/scimv2/api/service/GroupService.java    |   2 +-
 .../ext/scimv2/api/service/RootService.java     |  59 ---
 .../ext/scimv2/api/service/SCIMService.java     |  40 +-
 .../ext/scimv2/api/service/SearchService.java   |  41 ++
 .../ext/scimv2/api/service/UserService.java     |   2 +-
 .../syncope/ext/scimv2/cxf/AddETagFilter.java   |   2 +-
 .../scimv2/cxf/service/AbstractSCIMService.java | 235 -----------
 .../ext/scimv2/cxf/service/AbstractService.java | 160 ++++++++
 .../scimv2/cxf/service/GroupServiceImpl.java    |   4 +-
 .../ext/scimv2/cxf/service/RootServiceImpl.java |  68 ----
 .../ext/scimv2/cxf/service/SCIMServiceImpl.java |  68 ++++
 .../ext/scimv2/cxf/service/UserServiceImpl.java |   4 +-
 fit/console-reference/pom.xml                   |   6 +
 .../src/test/resources/rebel.xml                |   6 +
 fit/core-reference/pom.xml                      |  25 +-
 .../main/resources/all/scimv2-logic.properties  |  21 -
 .../org/apache/syncope/fit/AbstractITCase.java  |   4 +
 .../org/apache/syncope/fit/core/SCIMITCase.java |  31 ++
 fit/core-reference/src/test/resources/rebel.xml |   6 +
 68 files changed, 3291 insertions(+), 690 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/archetype/src/main/resources/archetype-resources/console/pom.xml
----------------------------------------------------------------------
diff --git a/archetype/src/main/resources/archetype-resources/console/pom.xml b/archetype/src/main/resources/archetype-resources/console/pom.xml
index 8646381..da2018f 100644
--- a/archetype/src/main/resources/archetype-resources/console/pom.xml
+++ b/archetype/src/main/resources/archetype-resources/console/pom.xml
@@ -141,6 +141,12 @@ under the License.
         </dependency>
         
         <dependency>
+          <groupId>org.apache.syncope.ext.scimv2</groupId>
+          <artifactId>syncope-ext-scimv2-client-console</artifactId>
+          <version>${syncope.version}</version>
+        </dependency>
+
+        <dependency>
           <groupId>org.flowable</groupId>
           <artifactId>flowable-ui-modeler-app</artifactId>            
           <type>war</type>

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/archetype/src/main/resources/archetype-resources/core/pom.xml
----------------------------------------------------------------------
diff --git a/archetype/src/main/resources/archetype-resources/core/pom.xml b/archetype/src/main/resources/archetype-resources/core/pom.xml
index aae48ce..8e68fe9 100644
--- a/archetype/src/main/resources/archetype-resources/core/pom.xml
+++ b/archetype/src/main/resources/archetype-resources/core/pom.xml
@@ -193,6 +193,17 @@ under the License.
         </dependency>
 
         <dependency>
+          <groupId>org.apache.syncope.ext.scimv2</groupId>
+          <artifactId>syncope-ext-scimv2-rest-cxf</artifactId>
+          <version>${project.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.syncope.ext.scimv2</groupId>
+          <artifactId>syncope-ext-scimv2-scim-rest-cxf</artifactId>
+          <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
           <groupId>org.apache.syncope.ext</groupId>
           <artifactId>syncope-ext-swagger-ui</artifactId>
           <version>${syncope.version}</version>

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java
index ea927a5..dbf222c 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java
@@ -100,7 +100,7 @@ public class ParametersDirectoryPanel
                 target.add(container);
             }
         });
-
+        modalDetails.size(Modal.Size.Medium);
         addInnerObject(modalDetails);
 
         this.addNewItemPanelBuilder(new AbstractModalPanelBuilder<AttrTO>(new AttrTO(), pageRef) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
index 5644e85..4768d16 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
@@ -224,7 +224,7 @@ public class RoleDirectoryPanel extends DirectoryPanel<RoleTO, RoleWrapper, Role
                             modal.show(false);
                             modal.close(target);
                         } catch (Exception e) {
-                            LOG.error("While updating onsole layout info for role {}", info.getKey(), e);
+                            LOG.error("While updating console layout info for role {}", info.getKey(), e);
                             SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
                                     ? e.getClass().getName() : e.getMessage());
                         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/client-console/pom.xml
----------------------------------------------------------------------
diff --git a/ext/scimv2/client-console/pom.xml b/ext/scimv2/client-console/pom.xml
new file mode 100644
index 0000000..7b02052
--- /dev/null
+++ b/ext/scimv2/client-console/pom.xml
@@ -0,0 +1,78 @@
+<?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.ext</groupId>
+    <artifactId>syncope-ext-scimv2</artifactId>
+    <version>2.1.0-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Ext: SCIMv2 Client Console</name>
+  <description>Apache Syncope Ext: SCIMv2 Client Console</description>
+  <groupId>org.apache.syncope.ext.scimv2</groupId>
+  <artifactId>syncope-ext-scimv2-client-console</artifactId>
+  <packaging>jar</packaging>
+  
+  <properties>
+    <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>javax.servlet-api</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-common-lib</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-rest-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.client</groupId>
+      <artifactId>syncope-client-console</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+      </plugin>
+    </plugins>
+    
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+        <filtering>true</filtering>
+      </resource>
+    </resources>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/pages/SCIMConf.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/pages/SCIMConf.java b/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/pages/SCIMConf.java
new file mode 100644
index 0000000..bd22f03
--- /dev/null
+++ b/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/pages/SCIMConf.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.client.console.pages;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.annotations.ExtPage;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.rest.SCIMConfRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.console.wicket.markup.html.form.JsonEditorPanel;
+import org.apache.syncope.common.lib.scim.SCIMComplexConf;
+import org.apache.syncope.common.lib.scim.SCIMEnterpriseUserConf;
+import org.apache.syncope.common.lib.scim.SCIMUserConf;
+import org.apache.syncope.common.lib.scim.SCIMUserNameConf;
+import org.apache.syncope.common.lib.scim.types.EmailCanonicalType;
+import org.apache.syncope.common.lib.scim.types.SCIMEntitlement;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+@ExtPage(label = "SCIM 2.0", icon = "fa-cloud", listEntitlement = SCIMEntitlement.SCIM_CONF_GET, priority = 100)
+public class SCIMConf extends BaseExtPage {
+
+    private static final long serialVersionUID = 9128779230455599119L;
+
+    private static final ObjectMapper MAPPER = new ObjectMapper();
+
+    private final SCIMConfRestClient restClient = new SCIMConfRestClient();
+
+    public SCIMConf(final PageParameters parameters) {
+        super(parameters);
+
+        body.add(BookmarkablePageLinkBuilder.build("dashboard", "dashboardBr", Dashboard.class));
+
+        final BaseModal<String> modal = new BaseModal<>("modal");
+        modal.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() {
+
+            private static final long serialVersionUID = 8804221891699487139L;
+
+            @Override
+            public void onClose(final AjaxRequestTarget target) {
+                modal.show(false);
+            }
+        });
+        modal.size(Modal.Size.Large);
+        modal.addSubmitButton();
+        body.add(modal);
+
+        WebMarkupContainer content = new WebMarkupContainer("content");
+        content.setOutputMarkupId(true);
+        body.add(content);
+
+        String confString = "";
+        try {
+            org.apache.syncope.common.lib.scim.SCIMConf conf = restClient.get();
+            if (conf.getUserConf() == null) {
+                conf.setUserConf(new SCIMUserConf());
+            }
+            if (conf.getUserConf().getName() == null) {
+                conf.getUserConf().setName(new SCIMUserNameConf());
+            }
+            if (conf.getUserConf().getEmails().isEmpty()) {
+                conf.getUserConf().getEmails().add(new SCIMComplexConf<EmailCanonicalType>());
+            }
+
+            if (conf.getEnterpriseUserConf() == null) {
+                conf.setEnterpriseUserConf(new SCIMEnterpriseUserConf());
+            }
+
+            confString = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(conf);
+        } catch (Exception e) {
+            LOG.error("While reading SCIM configuration", e);
+            SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
+                    ? e.getClass().getName() : e.getMessage());
+        }
+        final Model<String> confModel = Model.of(confString);
+
+        content.add(new AjaxLink<Void>("edit") {
+
+            private static final long serialVersionUID = -4331619903296515985L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                modal.header(new ResourceModel("editConf"));
+                modal.setContent(new JsonEditorPanel(modal, confModel, false, getPageReference()) {
+
+                    private static final long serialVersionUID = -8927036362466990179L;
+
+                    @Override
+                    public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
+                        try {
+                            restClient.set(MAPPER.readValue(
+                                    confModel.getObject(), org.apache.syncope.common.lib.scim.SCIMConf.class));
+
+                            SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
+                            modal.show(false);
+                            modal.close(target);
+                        } catch (Exception e) {
+                            LOG.error("While setting SCIM configuration", e);
+                            SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
+                                    ? e.getClass().getName() : e.getMessage());
+                        }
+                        ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
+                    }
+                });
+                modal.show(true);
+                target.add(modal);
+            }
+        });
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/rest/SCIMConfRestClient.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/rest/SCIMConfRestClient.java b/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/rest/SCIMConfRestClient.java
new file mode 100644
index 0000000..95ae663
--- /dev/null
+++ b/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/rest/SCIMConfRestClient.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.rest;
+
+import org.apache.syncope.common.lib.scim.SCIMConf;
+import org.apache.syncope.common.rest.api.service.SCIMConfService;
+
+public class SCIMConfRestClient extends BaseRestClient {
+
+    private static final long serialVersionUID = -8572714521320571470L;
+
+    public SCIMConf get() {
+        return getService(SCIMConfService.class).get();
+    }
+
+    public void set(final SCIMConf conf) {
+        getService(SCIMConfService.class).set(conf);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf.html
----------------------------------------------------------------------
diff --git a/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf.html b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf.html
new file mode 100644
index 0000000..aa1e725
--- /dev/null
+++ b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+  <wicket:extend>
+    <section class="content-header">
+      <h1>&nbsp;</h1>
+      <ol class="breadcrumb">
+        <li><a wicket:id="dashboardBr"><i class="fa fa-dashboard"></i> <wicket:message key="dashboard"/></a></li>
+        <li class="active"><wicket:message key="extensions"/></li>
+        <li class="active">SCIM 2.0</li>
+      </ol>
+    </section>
+
+    <section class="content" wicket:id="content">
+      <div class="logviewer-btn">
+        <a class="btn btn-primary" wicket:id="edit"> <wicket:message key="editConf"/>
+          <span class="fa fa-edit"></span>
+        </a>
+      </div>
+    </section>
+
+    <div wicket:id="modal"/>
+  </wicket:extend>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf.properties
----------------------------------------------------------------------
diff --git a/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf.properties b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf.properties
new file mode 100644
index 0000000..e7f31e6
--- /dev/null
+++ b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf.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.
+editConf=SCIM 2.0 configuration

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_it.properties
----------------------------------------------------------------------
diff --git a/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_it.properties b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_it.properties
new file mode 100644
index 0000000..3655a0f
--- /dev/null
+++ b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_it.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.
+editConf=Configurazione SCIM 2.0

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_pt_BR.properties
----------------------------------------------------------------------
diff --git a/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_pt_BR.properties b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_pt_BR.properties
new file mode 100644
index 0000000..e7f31e6
--- /dev/null
+++ b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_pt_BR.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.
+editConf=SCIM 2.0 configuration

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_ru.properties
----------------------------------------------------------------------
diff --git a/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_ru.properties b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_ru.properties
new file mode 100644
index 0000000..e7f31e6
--- /dev/null
+++ b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_ru.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.
+editConf=SCIM 2.0 configuration

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/common-lib/pom.xml
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/pom.xml b/ext/scimv2/common-lib/pom.xml
new file mode 100644
index 0000000..246688d
--- /dev/null
+++ b/ext/scimv2/common-lib/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<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.ext</groupId>
+    <artifactId>syncope-ext-scimv2</artifactId>
+    <version>2.1.0-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Ext: SCIMv2 Common Lib</name>
+  <description>Apache Syncope Ext: SCIMv2 Common Lib</description>
+  <groupId>org.apache.syncope.ext.scimv2</groupId>
+  <artifactId>syncope-ext-scimv2-common-lib</artifactId>
+  <packaging>jar</packaging>
+  
+  <properties>
+    <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.syncope.common</groupId>
+      <artifactId>syncope-common-lib</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMComplexConf.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMComplexConf.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMComplexConf.java
new file mode 100644
index 0000000..84cb3fa
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMComplexConf.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.scim;
+
+import java.io.Serializable;
+
+public class SCIMComplexConf<E extends Enum<?>> implements Serializable {
+
+    private static final long serialVersionUID = -6205072829179565927L;
+
+    private String value;
+
+    private String display;
+
+    private E type;
+
+    private boolean primary;
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(final String value) {
+        this.value = value;
+    }
+
+    public String getDisplay() {
+        return display;
+    }
+
+    public void setDisplay(final String display) {
+        this.display = display;
+    }
+
+    public E getType() {
+        return type;
+    }
+
+    public void setType(final E type) {
+        this.type = type;
+    }
+
+    public boolean isPrimary() {
+        return primary;
+    }
+
+    public void setPrimary(final boolean primary) {
+        this.primary = primary;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMConf.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMConf.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMConf.java
new file mode 100644
index 0000000..e7cc2a4
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMConf.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.scim;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import java.io.Serializable;
+import java.util.Date;
+import org.apache.commons.lang3.StringUtils;
+
+public class SCIMConf implements Serializable {
+
+    private static final long serialVersionUID = 5032136914118958611L;
+
+    public static final String KEY = "scimv2.conf";
+
+    private Date creationDate = new Date();
+
+    private Date lastChangeDate = new Date();
+
+    private int bulkMaxOperations = 1000;
+
+    private int bulkMaxPayloadSize = 1048576;
+
+    private int filterMaxResults = 200;
+
+    private SCIMUserConf userConf;
+
+    private SCIMEnterpriseUserConf enterpriseUserConf;
+
+    public Date getCreationDate() {
+        if (creationDate != null) {
+            return new Date(creationDate.getTime());
+        }
+        return null;
+    }
+
+    public void setCreationDate(final Date creationDate) {
+        if (creationDate != null) {
+            this.creationDate = new Date(creationDate.getTime());
+        } else {
+            this.creationDate = null;
+        }
+    }
+
+    public Date getLastChangeDate() {
+        if (lastChangeDate != null) {
+            return new Date(lastChangeDate.getTime());
+        }
+        return null;
+    }
+
+    public void setLastChangeDate(final Date lastChangeDate) {
+        if (lastChangeDate != null) {
+            this.lastChangeDate = new Date(lastChangeDate.getTime());
+        } else {
+            this.lastChangeDate = null;
+        }
+    }
+
+    @JsonIgnore
+    public String getETagValue() {
+        Date etagDate = getLastChangeDate() == null
+                ? getCreationDate() : getLastChangeDate();
+        return etagDate == null
+                ? StringUtils.EMPTY
+                : String.valueOf(etagDate.getTime());
+
+    }
+
+    public int getBulkMaxOperations() {
+        return bulkMaxOperations;
+    }
+
+    public void setBulkMaxOperations(final int bulkMaxOperations) {
+        this.bulkMaxOperations = bulkMaxOperations;
+    }
+
+    public int getBulkMaxPayloadSize() {
+        return bulkMaxPayloadSize;
+    }
+
+    public void setBulkMaxPayloadSize(final int bulkMaxPayloadSize) {
+        this.bulkMaxPayloadSize = bulkMaxPayloadSize;
+    }
+
+    public int getFilterMaxResults() {
+        return filterMaxResults;
+    }
+
+    public void setFilterMaxResults(final int filterMaxResults) {
+        this.filterMaxResults = filterMaxResults;
+    }
+
+    public SCIMUserConf getUserConf() {
+        return userConf;
+    }
+
+    public void setUserConf(final SCIMUserConf userConf) {
+        this.userConf = userConf;
+    }
+
+    public SCIMEnterpriseUserConf getEnterpriseUserConf() {
+        return enterpriseUserConf;
+    }
+
+    public void setEnterpriseUserConf(final SCIMEnterpriseUserConf enterpriseUserConf) {
+        this.enterpriseUserConf = enterpriseUserConf;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMEnterpriseUserConf.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMEnterpriseUserConf.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMEnterpriseUserConf.java
new file mode 100644
index 0000000..4cf7b88
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMEnterpriseUserConf.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.scim;
+
+import java.io.Serializable;
+
+public class SCIMEnterpriseUserConf implements Serializable {
+
+    private static final long serialVersionUID = 5929414914887282638L;
+
+    private String employeeNumber;
+
+    private String costCenter;
+
+    private String organization;
+
+    private String division;
+
+    private String department;
+
+    private SCIMManagerConf manager;
+
+    public String getEmployeeNumber() {
+        return employeeNumber;
+    }
+
+    public void setEmployeeNumber(final String employeeNumber) {
+        this.employeeNumber = employeeNumber;
+    }
+
+    public String getCostCenter() {
+        return costCenter;
+    }
+
+    public void setCostCenter(final String costCenter) {
+        this.costCenter = costCenter;
+    }
+
+    public String getOrganization() {
+        return organization;
+    }
+
+    public void setOrganization(final String organization) {
+        this.organization = organization;
+    }
+
+    public String getDivision() {
+        return division;
+    }
+
+    public void setDivision(final String division) {
+        this.division = division;
+    }
+
+    public String getDepartment() {
+        return department;
+    }
+
+    public void setDepartment(final String department) {
+        this.department = department;
+    }
+
+    public SCIMManagerConf getManager() {
+        return manager;
+    }
+
+    public void setManager(final SCIMManagerConf manager) {
+        this.manager = manager;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMManagerConf.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMManagerConf.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMManagerConf.java
new file mode 100644
index 0000000..481eb5f
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMManagerConf.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.scim;
+
+import java.io.Serializable;
+
+public class SCIMManagerConf implements Serializable {
+
+    private static final long serialVersionUID = -1443695570207406613L;
+
+    private String manager;
+
+    private String displayName;
+
+    public String getManager() {
+        return manager;
+    }
+
+    public void setManager(final String manager) {
+        this.manager = manager;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public void setDisplayName(final String displayName) {
+        this.displayName = displayName;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserAddressConf.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserAddressConf.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserAddressConf.java
new file mode 100644
index 0000000..ed5643a
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserAddressConf.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.scim;
+
+import java.io.Serializable;
+import org.apache.syncope.common.lib.scim.types.AddressCanonicalType;
+
+public class SCIMUserAddressConf implements Serializable {
+
+    private static final long serialVersionUID = 8093531407836615577L;
+
+    private String formatted;
+
+    private String streetAddress;
+
+    private String locality;
+
+    private String region;
+
+    private String postalCode;
+
+    private String country;
+
+    private AddressCanonicalType type;
+
+    private boolean primary;
+
+    public String getFormatted() {
+        return formatted;
+    }
+
+    public void setFormatted(final String formatted) {
+        this.formatted = formatted;
+    }
+
+    public String getStreetAddress() {
+        return streetAddress;
+    }
+
+    public void setStreetAddress(final String streetAddress) {
+        this.streetAddress = streetAddress;
+    }
+
+    public String getLocality() {
+        return locality;
+    }
+
+    public void setLocality(final String locality) {
+        this.locality = locality;
+    }
+
+    public String getRegion() {
+        return region;
+    }
+
+    public void setRegion(final String region) {
+        this.region = region;
+    }
+
+    public String getPostalCode() {
+        return postalCode;
+    }
+
+    public void setPostalCode(final String postalCode) {
+        this.postalCode = postalCode;
+    }
+
+    public String getCountry() {
+        return country;
+    }
+
+    public void setCountry(final String country) {
+        this.country = country;
+    }
+
+    public AddressCanonicalType getType() {
+        return type;
+    }
+
+    public void setType(final AddressCanonicalType type) {
+        this.type = type;
+    }
+
+    public boolean isPrimary() {
+        return primary;
+    }
+
+    public void setPrimary(final boolean primary) {
+        this.primary = primary;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserConf.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserConf.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserConf.java
new file mode 100644
index 0000000..7d1be73
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserConf.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.scim;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.syncope.common.lib.scim.types.EmailCanonicalType;
+import org.apache.syncope.common.lib.scim.types.IMCanonicalType;
+import org.apache.syncope.common.lib.scim.types.PhoneNumberCanonicalType;
+import org.apache.syncope.common.lib.scim.types.PhotoCanonicalType;
+
+public class SCIMUserConf implements Serializable {
+
+    private static final long serialVersionUID = -2700011089067219156L;
+
+    private SCIMUserNameConf name;
+
+    private String displayName;
+
+    private String nickName;
+
+    private String profileUrl;
+
+    private String title;
+
+    private String userType;
+
+    private String preferredLanguage;
+
+    private String locale;
+
+    private String timezone;
+
+    private final List<SCIMComplexConf<EmailCanonicalType>> emails = new ArrayList<>();
+
+    private final List<SCIMComplexConf<PhoneNumberCanonicalType>> phoneNumbers = new ArrayList<>();
+
+    private final List<SCIMComplexConf<IMCanonicalType>> ims = new ArrayList<>();
+
+    private final List<SCIMComplexConf<PhotoCanonicalType>> photos = new ArrayList<>();
+
+    private final List<SCIMUserAddressConf> addresses = new ArrayList<>();
+
+    private final List<String> x509Certificates = new ArrayList<>();
+
+    public SCIMUserNameConf getName() {
+        return name;
+    }
+
+    public void setName(final SCIMUserNameConf name) {
+        this.name = name;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public void setDisplayName(final String displayName) {
+        this.displayName = displayName;
+    }
+
+    public String getNickName() {
+        return nickName;
+    }
+
+    public void setNickName(final String nickName) {
+        this.nickName = nickName;
+    }
+
+    public String getProfileUrl() {
+        return profileUrl;
+    }
+
+    public void setProfileUrl(final String profileUrl) {
+        this.profileUrl = profileUrl;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(final String title) {
+        this.title = title;
+    }
+
+    public String getUserType() {
+        return userType;
+    }
+
+    public void setUserType(final String userType) {
+        this.userType = userType;
+    }
+
+    public String getPreferredLanguage() {
+        return preferredLanguage;
+    }
+
+    public void setPreferredLanguage(final String preferredLanguage) {
+        this.preferredLanguage = preferredLanguage;
+    }
+
+    public String getLocale() {
+        return locale;
+    }
+
+    public void setLocale(final String locale) {
+        this.locale = locale;
+    }
+
+    public String getTimezone() {
+        return timezone;
+    }
+
+    public void setTimezone(final String timezone) {
+        this.timezone = timezone;
+    }
+
+    public List<SCIMComplexConf<EmailCanonicalType>> getEmails() {
+        return emails;
+    }
+
+    public List<SCIMComplexConf<PhoneNumberCanonicalType>> getPhoneNumbers() {
+        return phoneNumbers;
+    }
+
+    public List<SCIMComplexConf<IMCanonicalType>> getIms() {
+        return ims;
+    }
+
+    public List<SCIMComplexConf<PhotoCanonicalType>> getPhotos() {
+        return photos;
+    }
+
+    public List<SCIMUserAddressConf> getAddresses() {
+        return addresses;
+    }
+
+    public List<String> getX509Certificates() {
+        return x509Certificates;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserNameConf.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserNameConf.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserNameConf.java
new file mode 100644
index 0000000..2f2db0f
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserNameConf.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.scim;
+
+import java.io.Serializable;
+
+public class SCIMUserNameConf implements Serializable {
+
+    private static final long serialVersionUID = -2256008193008290376L;
+
+    private String formatted;
+
+    private String familyName;
+
+    private String givenName;
+
+    private String middleName;
+
+    private String honorificPrefix;
+
+    private String honorificSuffix;
+
+    public String getFormatted() {
+        return formatted;
+    }
+
+    public void setFormatted(final String formatted) {
+        this.formatted = formatted;
+    }
+
+    public String getFamilyName() {
+        return familyName;
+    }
+
+    public void setFamilyName(final String familyName) {
+        this.familyName = familyName;
+    }
+
+    public String getGivenName() {
+        return givenName;
+    }
+
+    public void setGivenName(final String givenName) {
+        this.givenName = givenName;
+    }
+
+    public String getMiddleName() {
+        return middleName;
+    }
+
+    public void setMiddleName(final String middleName) {
+        this.middleName = middleName;
+    }
+
+    public String getHonorificPrefix() {
+        return honorificPrefix;
+    }
+
+    public void setHonorificPrefix(final String honorificPrefix) {
+        this.honorificPrefix = honorificPrefix;
+    }
+
+    public String getHonorificSuffix() {
+        return honorificSuffix;
+    }
+
+    public void setHonorificSuffix(final String honorificSuffix) {
+        this.honorificSuffix = honorificSuffix;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/AddressCanonicalType.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/AddressCanonicalType.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/AddressCanonicalType.java
new file mode 100644
index 0000000..cf2cb13
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/AddressCanonicalType.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.common.lib.scim.types;
+
+public enum AddressCanonicalType {
+    work,
+    home,
+    other
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/EmailCanonicalType.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/EmailCanonicalType.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/EmailCanonicalType.java
new file mode 100644
index 0000000..986c9f6
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/EmailCanonicalType.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.common.lib.scim.types;
+
+public enum EmailCanonicalType {
+    work,
+    home,
+    other
+
+}

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

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/PhoneNumberCanonicalType.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/PhoneNumberCanonicalType.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/PhoneNumberCanonicalType.java
new file mode 100644
index 0000000..72ff342
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/PhoneNumberCanonicalType.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.common.lib.scim.types;
+
+public enum PhoneNumberCanonicalType {
+    work,
+    home,
+    mobile,
+    fax,
+    pager,
+    other
+
+}

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

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/SCIMEntitlement.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/SCIMEntitlement.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/SCIMEntitlement.java
new file mode 100644
index 0000000..8a8a1ae
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/SCIMEntitlement.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.scim.types;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Collections;
+import java.util.Set;
+import java.util.TreeSet;
+
+public final class SCIMEntitlement {
+
+    public static final String SCIM_CONF_GET = "SCIM_CONF_GET";
+
+    public static final String SCIM_CONF_SET = "SCIM_CONF_SET";
+
+    private static final Set<String> VALUES;
+
+    static {
+        Set<String> values = new TreeSet<>();
+        for (Field field : SCIMEntitlement.class.getDeclaredFields()) {
+            if (Modifier.isStatic(field.getModifiers()) && String.class.equals(field.getType())) {
+                values.add(field.getName());
+            }
+        }
+        VALUES = Collections.unmodifiableSet(values);
+    }
+
+    public static Set<String> values() {
+        return VALUES;
+    }
+
+    private SCIMEntitlement() {
+        // private constructor for static utility class
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/logic/pom.xml
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/pom.xml b/ext/scimv2/logic/pom.xml
index 4569445..204a3bd 100644
--- a/ext/scimv2/logic/pom.xml
+++ b/ext/scimv2/logic/pom.xml
@@ -52,6 +52,12 @@ under the License.
     </dependency>
     
     <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-common-lib</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    
+    <dependency>
       <groupId>org.antlr</groupId>
       <artifactId>antlr4-runtime</artifactId>
     </dependency>

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/RootLogic.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/RootLogic.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/RootLogic.java
deleted file mode 100644
index 75d0ecf..0000000
--- a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/RootLogic.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.logic;
-
-import java.lang.reflect.Method;
-import java.net.URI;
-import java.util.Arrays;
-import java.util.List;
-import javax.ws.rs.NotFoundException;
-import javax.ws.rs.core.UriBuilder;
-import org.apache.syncope.common.lib.AbstractBaseBean;
-import org.apache.syncope.core.logic.init.SCIMLoader;
-import org.apache.syncope.ext.scimv2.api.data.AuthenticationScheme;
-import org.apache.syncope.ext.scimv2.api.data.BulkConfigurationOption;
-import org.apache.syncope.ext.scimv2.api.data.ConfigurationOption;
-import org.apache.syncope.ext.scimv2.api.data.FilterConfigurationOption;
-import org.apache.syncope.ext.scimv2.api.data.Meta;
-import org.apache.syncope.ext.scimv2.api.data.ResourceType;
-import org.apache.syncope.ext.scimv2.api.data.SchemaExtension;
-import org.apache.syncope.ext.scimv2.api.data.ServiceProviderConfig;
-import org.apache.syncope.ext.scimv2.api.type.Resource;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.stereotype.Component;
-
-@Component
-public class RootLogic extends AbstractLogic<AbstractBaseBean> {
-
-    private static final Object MONITOR = new Object();
-
-    private static ServiceProviderConfig SERVICE_PROVIDER_CONFIG;
-
-    private static ResourceType USER;
-
-    private static ResourceType GROUP;
-
-    @Autowired
-    private SCIMLoader loader;
-
-    @PreAuthorize("isAuthenticated()")
-    public ServiceProviderConfig serviceProviderConfig() {
-        synchronized (MONITOR) {
-            if (SERVICE_PROVIDER_CONFIG == null) {
-                SERVICE_PROVIDER_CONFIG = new ServiceProviderConfig(
-                        new ConfigurationOption(true),
-                        new BulkConfigurationOption(
-                                true, loader.getBulkMaxOperations(), loader.getBulkMaxPayloadSize()),
-                        new FilterConfigurationOption(true, loader.getFilterMaxResults()),
-                        new ConfigurationOption(true),
-                        new ConfigurationOption(true),
-                        new ConfigurationOption(true));
-                SERVICE_PROVIDER_CONFIG.getAuthenticationSchemes().add(new AuthenticationScheme(
-                        "JSON Web Token",
-                        "Apache Syncope JWT authentication",
-                        URI.create("http://www.rfc-editor.org/info/rfc6750"),
-                        URI.create("https://syncope.apache.org/docs/"
-                                + "reference-guide.html#rest-authentication-and-authorization"),
-                        "oauthbearertoken",
-                        true));
-                SERVICE_PROVIDER_CONFIG.getAuthenticationSchemes().add(new AuthenticationScheme(
-                        "HTTP Basic",
-                        "Apache Syncope HTTP Basic authentication",
-                        URI.create("http://www.rfc-editor.org/info/rfc2617"),
-                        URI.create("https://syncope.apache.org/docs/"
-                                + "reference-guide.html#rest-authentication-and-authorization"),
-                        "httpbasic",
-                        false));
-            }
-        }
-        return SERVICE_PROVIDER_CONFIG;
-    }
-
-    @PreAuthorize("isAuthenticated()")
-    public List<ResourceType> resourceTypes(final UriBuilder uriBuilder) {
-        synchronized (MONITOR) {
-            if (USER == null) {
-                USER = new ResourceType("User", "User", "/Users", "User Account", Resource.User.schema(),
-                        new Meta(Resource.ResourceType,
-                                null, null, null, uriBuilder.path("User").build().toASCIIString()));
-                USER.getSchemaExtensions().add(new SchemaExtension(Resource.EnterpriseUser.schema(), true));
-            }
-            if (GROUP == null) {
-                GROUP = new ResourceType("Group", "Group", "/Groups", "Group", Resource.Group.schema(),
-                        new Meta(Resource.ResourceType,
-                                null, null, null, uriBuilder.path("Group").build().toASCIIString()));
-            }
-        }
-
-        return Arrays.asList(USER, GROUP);
-    }
-
-    @PreAuthorize("isAuthenticated()")
-    public ResourceType resourceType(final UriBuilder uriBuilder, final String type) {
-        if (Resource.User.name().equals(type)) {
-            resourceTypes(uriBuilder);
-            return USER;
-        } else if (Resource.Group.name().equals(type)) {
-            resourceTypes(uriBuilder);
-            return GROUP;
-        } else {
-            throw new IllegalArgumentException("Unsupported resource type: " + type);
-        }
-    }
-
-    @PreAuthorize("isAuthenticated()")
-    public String schemas() {
-        return loader.getSchemas();
-    }
-
-    @PreAuthorize("isAuthenticated()")
-    public String schema(final String schema) {
-        String found = loader.getSchema(schema);
-        if (found == null) {
-            throw new NotFoundException("Schema " + schema);
-        }
-
-        return found;
-    }
-
-    @Override
-    protected AbstractBaseBean resolveReference(final Method method, final Object... args)
-            throws UnresolvedReferenceException {
-
-        throw new UnresolvedReferenceException();
-    }
-
-}


[2/6] syncope git commit: [SYNCOPE-152] SCIM configuration including attribute mapping + console extension

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java
new file mode 100644
index 0000000..d15d30b
--- /dev/null
+++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java
@@ -0,0 +1,394 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.logic;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.EntityTOUtils;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.scim.SCIMComplexConf;
+import org.apache.syncope.common.lib.scim.SCIMConf;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.core.logic.scim.SCIMConfManager;
+import org.apache.syncope.core.persistence.api.dao.AnyDAO;
+import org.apache.syncope.core.persistence.api.dao.search.MembershipCond;
+import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.core.spring.security.AuthDataAccessor;
+import org.apache.syncope.ext.scimv2.api.data.Value;
+import org.apache.syncope.ext.scimv2.api.data.Group;
+import org.apache.syncope.ext.scimv2.api.data.Member;
+import org.apache.syncope.ext.scimv2.api.data.Meta;
+import org.apache.syncope.ext.scimv2.api.data.SCIMComplexValue;
+import org.apache.syncope.ext.scimv2.api.data.SCIMEnterpriseInfo;
+import org.apache.syncope.ext.scimv2.api.data.SCIMGroup;
+import org.apache.syncope.ext.scimv2.api.data.SCIMUser;
+import org.apache.syncope.ext.scimv2.api.data.SCIMUserAddress;
+import org.apache.syncope.ext.scimv2.api.data.SCIMUserManager;
+import org.apache.syncope.ext.scimv2.api.data.SCIMUserName;
+import org.apache.syncope.ext.scimv2.api.type.Function;
+import org.apache.syncope.ext.scimv2.api.type.Resource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SCIMDataBinder {
+
+    protected static final Logger LOG = LoggerFactory.getLogger(SCIMDataBinder.class);
+
+    @Autowired
+    private SCIMConfManager confManager;
+
+    @Autowired
+    private UserLogic userLogic;
+
+    @Autowired
+    private AuthDataAccessor authDataAccessor;
+
+    private <E extends Enum<?>> void fill(
+            final Map<String, AttrTO> attrs,
+            final List<SCIMComplexConf<E>> confs,
+            final List<SCIMComplexValue> values) {
+
+        confs.forEach(conf -> {
+            SCIMComplexValue value = new SCIMComplexValue();
+
+            if (conf.getValue() != null && attrs.containsKey(conf.getValue())) {
+                value.setValue(attrs.get(conf.getValue()).getValues().get(0));
+            }
+            if (conf.getDisplay() != null && attrs.containsKey(conf.getDisplay())) {
+                value.setDisplay(attrs.get(conf.getDisplay()).getValues().get(0));
+            }
+            if (conf.getType() != null) {
+                value.setType(conf.getType().name());
+            }
+            if (conf.isPrimary()) {
+                value.setPrimary(true);
+            }
+
+            if (!value.isEmpty()) {
+                values.add(value);
+            }
+        });
+    }
+
+    public SCIMUser toSCIMUser(final UserTO userTO, final String location) {
+        SCIMConf conf = confManager.get();
+
+        SCIMUser user = new SCIMUser(
+                userTO.getKey(),
+                Collections.singletonList(Resource.User.schema()),
+                new Meta(
+                        Resource.User,
+                        userTO.getCreationDate(),
+                        userTO.getLastChangeDate() == null
+                        ? userTO.getCreationDate() : userTO.getLastChangeDate(),
+                        userTO.getETagValue(),
+                        location),
+                userTO.getUsername(),
+                !userTO.isSuspended());
+
+        Map<String, AttrTO> attrs = new HashMap<>();
+        attrs.putAll(EntityTOUtils.buildAttrMap(userTO.getPlainAttrs()));
+        attrs.putAll(EntityTOUtils.buildAttrMap(userTO.getDerAttrs()));
+        attrs.putAll(EntityTOUtils.buildAttrMap(userTO.getVirAttrs()));
+
+        if (conf.getUserConf() != null) {
+            if (conf.getUserConf().getName() != null) {
+                SCIMUserName name = new SCIMUserName();
+
+                if (conf.getUserConf().getName().getFamilyName() != null
+                        && attrs.containsKey(conf.getUserConf().getName().getFamilyName())) {
+
+                    name.setFamilyName(attrs.get(conf.getUserConf().getName().getFamilyName()).getValues().get(0));
+                }
+                if (conf.getUserConf().getName().getFormatted() != null
+                        && attrs.containsKey(conf.getUserConf().getName().getFormatted())) {
+
+                    name.setFormatted(attrs.get(conf.getUserConf().getName().getFormatted()).getValues().get(0));
+                }
+                if (conf.getUserConf().getName().getGivenName() != null
+                        && attrs.containsKey(conf.getUserConf().getName().getGivenName())) {
+
+                    name.setGivenName(attrs.get(conf.getUserConf().getName().getGivenName()).getValues().get(0));
+                }
+                if (conf.getUserConf().getName().getHonorificPrefix() != null
+                        && attrs.containsKey(conf.getUserConf().getName().getHonorificPrefix())) {
+
+                    name.setHonorificPrefix(
+                            attrs.get(conf.getUserConf().getName().getHonorificPrefix()).getValues().get(0));
+                }
+                if (conf.getUserConf().getName().getHonorificSuffix() != null
+                        && attrs.containsKey(conf.getUserConf().getName().getHonorificSuffix())) {
+
+                    name.setHonorificSuffix(
+                            attrs.get(conf.getUserConf().getName().getHonorificSuffix()).getValues().get(0));
+                }
+                if (conf.getUserConf().getName().getMiddleName() != null
+                        && attrs.containsKey(conf.getUserConf().getName().getMiddleName())) {
+
+                    name.setMiddleName(attrs.get(conf.getUserConf().getName().getMiddleName()).getValues().get(0));
+                }
+
+                if (!name.isEmpty()) {
+                    user.setName(name);
+                }
+            }
+
+            if (conf.getUserConf().getDisplayName() != null
+                    && attrs.containsKey(conf.getUserConf().getDisplayName())) {
+
+                user.setDisplayName(attrs.get(conf.getUserConf().getDisplayName()).getValues().get(0));
+            }
+
+            if (conf.getUserConf().getNickName() != null
+                    && attrs.containsKey(conf.getUserConf().getNickName())) {
+
+                user.setNickName(attrs.get(conf.getUserConf().getNickName()).getValues().get(0));
+            }
+
+            if (conf.getUserConf().getProfileUrl() != null
+                    && attrs.containsKey(conf.getUserConf().getProfileUrl())) {
+
+                user.setProfileUrl(attrs.get(conf.getUserConf().getProfileUrl()).getValues().get(0));
+            }
+
+            if (conf.getUserConf().getTitle() != null
+                    && attrs.containsKey(conf.getUserConf().getTitle())) {
+
+                user.setTitle(attrs.get(conf.getUserConf().getTitle()).getValues().get(0));
+            }
+
+            if (conf.getUserConf().getUserType() != null
+                    && attrs.containsKey(conf.getUserConf().getUserType())) {
+
+                user.setUserType(attrs.get(conf.getUserConf().getUserType()).getValues().get(0));
+            }
+
+            if (conf.getUserConf().getPreferredLanguage() != null
+                    && attrs.containsKey(conf.getUserConf().getPreferredLanguage())) {
+
+                user.setPreferredLanguage(attrs.get(conf.getUserConf().getPreferredLanguage()).getValues().get(0));
+            }
+
+            if (conf.getUserConf().getLocale() != null
+                    && attrs.containsKey(conf.getUserConf().getLocale())) {
+
+                user.setLocale(attrs.get(conf.getUserConf().getLocale()).getValues().get(0));
+            }
+
+            if (conf.getUserConf().getTimezone() != null
+                    && attrs.containsKey(conf.getUserConf().getTimezone())) {
+
+                user.setTimezone(attrs.get(conf.getUserConf().getTimezone()).getValues().get(0));
+            }
+
+            fill(attrs, conf.getUserConf().getEmails(), user.getEmails());
+            fill(attrs, conf.getUserConf().getPhoneNumbers(), user.getPhoneNumbers());
+            fill(attrs, conf.getUserConf().getIms(), user.getIms());
+            fill(attrs, conf.getUserConf().getPhotos(), user.getPhotos());
+            conf.getUserConf().getAddresses().forEach(addressConf -> {
+                SCIMUserAddress address = new SCIMUserAddress();
+
+                if (addressConf.getFormatted() != null && attrs.containsKey(addressConf.getFormatted())) {
+                    address.setFormatted(attrs.get(addressConf.getFormatted()).getValues().get(0));
+                }
+                if (addressConf.getStreetAddress() != null && attrs.containsKey(addressConf.getStreetAddress())) {
+                    address.setStreetAddress(attrs.get(addressConf.getStreetAddress()).getValues().get(0));
+                }
+                if (addressConf.getLocality() != null && attrs.containsKey(addressConf.getLocality())) {
+                    address.setLocality(attrs.get(addressConf.getLocality()).getValues().get(0));
+                }
+                if (addressConf.getRegion() != null && attrs.containsKey(addressConf.getRegion())) {
+                    address.setRegion(attrs.get(addressConf.getRegion()).getValues().get(0));
+                }
+                if (addressConf.getCountry() != null && attrs.containsKey(addressConf.getCountry())) {
+                    address.setCountry(attrs.get(addressConf.getCountry()).getValues().get(0));
+                }
+                if (addressConf.getType() != null) {
+                    address.setType(addressConf.getType().name());
+                }
+                if (addressConf.isPrimary()) {
+                    address.setPrimary(true);
+                }
+
+                if (!address.isEmpty()) {
+                    user.getAddresses().add(address);
+                }
+            });
+
+            conf.getUserConf().getX509Certificates().stream().
+                    filter(certificate -> attrs.containsKey(certificate)).
+                    forEachOrdered(certificate -> {
+                        user.getX509Certificates().add(new Value(attrs.get(certificate).getValues().get(0)));
+                    });
+        }
+
+        if (conf.getEnterpriseUserConf() != null) {
+            SCIMEnterpriseInfo enterpriseInfo = new SCIMEnterpriseInfo();
+
+            if (conf.getEnterpriseUserConf().getEmployeeNumber() != null
+                    && attrs.containsKey(conf.getEnterpriseUserConf().getEmployeeNumber())) {
+
+                enterpriseInfo.setEmployeeNumber(
+                        attrs.get(conf.getEnterpriseUserConf().getEmployeeNumber()).getValues().get(0));
+            }
+            if (conf.getEnterpriseUserConf().getCostCenter() != null
+                    && attrs.containsKey(conf.getEnterpriseUserConf().getCostCenter())) {
+
+                enterpriseInfo.setCostCenter(
+                        attrs.get(conf.getEnterpriseUserConf().getCostCenter()).getValues().get(0));
+            }
+            if (conf.getEnterpriseUserConf().getOrganization() != null
+                    && attrs.containsKey(conf.getEnterpriseUserConf().getOrganization())) {
+
+                enterpriseInfo.setOrganization(
+                        attrs.get(conf.getEnterpriseUserConf().getOrganization()).getValues().get(0));
+            }
+            if (conf.getEnterpriseUserConf().getDivision() != null
+                    && attrs.containsKey(conf.getEnterpriseUserConf().getDivision())) {
+
+                enterpriseInfo.setDivision(
+                        attrs.get(conf.getEnterpriseUserConf().getDivision()).getValues().get(0));
+            }
+            if (conf.getEnterpriseUserConf().getDepartment() != null
+                    && attrs.containsKey(conf.getEnterpriseUserConf().getDepartment())) {
+
+                enterpriseInfo.setDepartment(
+                        attrs.get(conf.getEnterpriseUserConf().getDepartment()).getValues().get(0));
+            }
+            if (conf.getEnterpriseUserConf().getManager() != null) {
+                SCIMUserManager manager = new SCIMUserManager();
+
+                if (conf.getEnterpriseUserConf().getManager().getManager() != null
+                        && attrs.containsKey(conf.getEnterpriseUserConf().getManager().getManager())) {
+
+                    try {
+                        UserTO userManager = userLogic.read(
+                                attrs.get(conf.getEnterpriseUserConf().getManager().getManager()).getValues().get(0));
+                        manager.setValue(userManager.getKey());
+                        manager.setRef(
+                                StringUtils.substringBefore(location, "/Users") + "/Users/" + userManager.getKey());
+
+                        if (conf.getEnterpriseUserConf().getManager().getDisplayName() != null) {
+                            AttrTO displayName = userManager.getPlainAttr(
+                                    conf.getEnterpriseUserConf().getManager().getDisplayName()).orElse(null);
+                            if (displayName == null) {
+                                displayName = userManager.getDerAttr(
+                                        conf.getEnterpriseUserConf().getManager().getDisplayName()).orElse(null);
+                            }
+                            if (displayName == null) {
+                                displayName = userManager.getVirAttr(
+                                        conf.getEnterpriseUserConf().getManager().getDisplayName()).orElse(null);
+                            }
+                            if (displayName != null) {
+                                manager.setDisplayName(displayName.getValues().get(0));
+                            }
+                        }
+                    } catch (Exception e) {
+                        LOG.error("Could not read attribute {}",
+                                conf.getEnterpriseUserConf().getManager().getManager(), e);
+                    }
+                }
+
+                if (!manager.isEmpty()) {
+                    enterpriseInfo.setManager(manager);
+                }
+            }
+
+            if (!enterpriseInfo.isEmpty()) {
+                user.setEnterpriseInfo(enterpriseInfo);
+            }
+        }
+
+        userTO.getMemberships().forEach(membership -> {
+            user.getGroups().add(new Group(
+                    membership.getGroupKey(),
+                    StringUtils.substringBefore(location, "/Users") + "/Groups/" + membership.getGroupKey(),
+                    membership.getGroupName(),
+                    Function.direct));
+        });
+        userTO.getDynMemberships().forEach(membership -> {
+            user.getGroups().add(new Group(
+                    membership.getGroupKey(),
+                    StringUtils.substringBefore(location, "/Users") + "/Groups/" + membership.getGroupKey(),
+                    membership.getGroupName(),
+                    Function.indirect));
+        });
+
+        authDataAccessor.getAuthorities(userTO.getUsername()).forEach(authority -> {
+            user.getEntitlements().add(new Value(authority.getAuthority() + " on Realm(s) " + authority.getRealms()));
+        });
+
+        userTO.getRoles().forEach(role -> {
+            user.getRoles().add(new Value(role));
+        });
+
+        return user;
+    }
+
+    public SCIMGroup toSCIMGroup(final GroupTO groupTO, final String location) {
+        SCIMGroup group = new SCIMGroup(
+                groupTO.getKey(),
+                Collections.singletonList(Resource.Group.schema()),
+                new Meta(
+                        Resource.Group,
+                        groupTO.getCreationDate(),
+                        groupTO.getLastChangeDate() == null
+                        ? groupTO.getCreationDate() : groupTO.getLastChangeDate(),
+                        groupTO.getETagValue(),
+                        location),
+                groupTO.getName());
+
+        MembershipCond membCond = new MembershipCond();
+        membCond.setGroup(groupTO.getKey());
+        SearchCond searchCond = SearchCond.getLeafCond(membCond);
+
+        int count = userLogic.
+                search(searchCond, 1, 1, Collections.<OrderByClause>emptyList(), SyncopeConstants.ROOT_REALM, false).
+                getLeft();
+
+        for (int page = 1; page <= (count / AnyDAO.DEFAULT_PAGE_SIZE) + 1; page++) {
+            List<UserTO> users = userLogic.search(
+                    searchCond,
+                    page,
+                    AnyDAO.DEFAULT_PAGE_SIZE,
+                    Collections.<OrderByClause>emptyList(),
+                    SyncopeConstants.ROOT_REALM,
+                    false).
+                    getRight();
+            users.forEach(userTO -> {
+                group.getMembers().add(new Member(
+                        userTO.getKey(),
+                        StringUtils.substringBefore(location, "/Groups") + "/Users/" + userTO.getKey(),
+                        userTO.getUsername(),
+                        Resource.User));
+            });
+        }
+
+        return group;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMLogic.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMLogic.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMLogic.java
new file mode 100644
index 0000000..11085fb
--- /dev/null
+++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMLogic.java
@@ -0,0 +1,198 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.logic;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.core.UriBuilder;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+import org.apache.syncope.common.lib.scim.SCIMConf;
+import org.apache.syncope.core.logic.scim.SCIMConfManager;
+import org.apache.syncope.ext.scimv2.api.data.AuthenticationScheme;
+import org.apache.syncope.ext.scimv2.api.data.BulkConfigurationOption;
+import org.apache.syncope.ext.scimv2.api.data.ConfigurationOption;
+import org.apache.syncope.ext.scimv2.api.data.FilterConfigurationOption;
+import org.apache.syncope.ext.scimv2.api.data.Meta;
+import org.apache.syncope.ext.scimv2.api.data.ResourceType;
+import org.apache.syncope.ext.scimv2.api.data.SchemaExtension;
+import org.apache.syncope.ext.scimv2.api.data.ServiceProviderConfig;
+import org.apache.syncope.ext.scimv2.api.type.Resource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SCIMLogic extends AbstractLogic<AbstractBaseBean> {
+
+    private static final String SCHEMAS_JSON = "schemas.json";
+
+    private static final Object MONITOR = new Object();
+
+    private static ServiceProviderConfig SERVICE_PROVIDER_CONFIG;
+
+    private static ResourceType USER;
+
+    private static ResourceType GROUP;
+
+    private static String SCHEMAS;
+
+    private static final Map<String, String> SCHEMA_MAP = new HashMap<>();
+
+    @Autowired
+    private SCIMConfManager confManager;
+
+    private void init() {
+        try {
+            ObjectMapper mapper = new ObjectMapper();
+            JsonNode tree = mapper.readTree(getClass().getResourceAsStream("/" + SCHEMAS_JSON));
+            if (!tree.isArray()) {
+                throw new IOException("JSON node is not a tree");
+            }
+
+            ArrayNode schemaArray = (ArrayNode) tree;
+            SCHEMAS = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(tree);
+
+            for (JsonNode schema : schemaArray) {
+                SCHEMA_MAP.put(schema.get("id").asText(), mapper.writeValueAsString(schema));
+            }
+        } catch (IOException e) {
+            LOG.error("Could not parse the default schema definitions", e);
+        }
+    }
+
+    @PreAuthorize("isAuthenticated()")
+    public ServiceProviderConfig serviceProviderConfig(final UriBuilder uriBuilder) {
+        synchronized (MONITOR) {
+            if (SCHEMAS == null) {
+                init();
+            }
+
+            if (SERVICE_PROVIDER_CONFIG == null) {
+                SCIMConf conf = confManager.get();
+
+                SERVICE_PROVIDER_CONFIG = new ServiceProviderConfig(
+                        new Meta(
+                                Resource.ServiceProviderConfig,
+                                conf.getCreationDate(),
+                                conf.getLastChangeDate(),
+                                conf.getETagValue(),
+                                uriBuilder.build().toASCIIString()),
+                        new ConfigurationOption(true),
+                        new BulkConfigurationOption(true, conf.getBulkMaxOperations(), conf.getBulkMaxPayloadSize()),
+                        new FilterConfigurationOption(true, conf.getFilterMaxResults()),
+                        new ConfigurationOption(true),
+                        new ConfigurationOption(true),
+                        new ConfigurationOption(true));
+                SERVICE_PROVIDER_CONFIG.getAuthenticationSchemes().add(new AuthenticationScheme(
+                        "JSON Web Token",
+                        "Apache Syncope JWT authentication",
+                        URI.create("http://www.rfc-editor.org/info/rfc6750"),
+                        URI.create("https://syncope.apache.org/docs/"
+                                + "reference-guide.html#rest-authentication-and-authorization"),
+                        "oauthbearertoken",
+                        true));
+                SERVICE_PROVIDER_CONFIG.getAuthenticationSchemes().add(new AuthenticationScheme(
+                        "HTTP Basic",
+                        "Apache Syncope HTTP Basic authentication",
+                        URI.create("http://www.rfc-editor.org/info/rfc2617"),
+                        URI.create("https://syncope.apache.org/docs/"
+                                + "reference-guide.html#rest-authentication-and-authorization"),
+                        "httpbasic",
+                        false));
+            }
+        }
+        return SERVICE_PROVIDER_CONFIG;
+    }
+
+    @PreAuthorize("isAuthenticated()")
+    public List<ResourceType> resourceTypes(final UriBuilder uriBuilder) {
+        synchronized (MONITOR) {
+            if (USER == null) {
+                USER = new ResourceType("User", "User", "/Users", "User Account", Resource.User.schema(),
+                        new Meta(Resource.ResourceType,
+                                null, null, null, uriBuilder.path("User").build().toASCIIString()));
+                USER.getSchemaExtensions().add(new SchemaExtension(Resource.EnterpriseUser.schema(), true));
+            }
+            if (GROUP == null) {
+                GROUP = new ResourceType("Group", "Group", "/Groups", "Group", Resource.Group.schema(),
+                        new Meta(Resource.ResourceType,
+                                null, null, null, uriBuilder.path("Group").build().toASCIIString()));
+            }
+        }
+
+        return Arrays.asList(USER, GROUP);
+    }
+
+    @PreAuthorize("isAuthenticated()")
+    public ResourceType resourceType(final UriBuilder uriBuilder, final String type) {
+        if (Resource.User.name().equals(type)) {
+            resourceTypes(uriBuilder);
+            return USER;
+        } else if (Resource.Group.name().equals(type)) {
+            resourceTypes(uriBuilder);
+            return GROUP;
+        } else {
+            throw new IllegalArgumentException("Unsupported resource type: " + type);
+        }
+    }
+
+    @PreAuthorize("isAuthenticated()")
+    public String schemas() {
+        synchronized (MONITOR) {
+            if (SCHEMAS == null) {
+                init();
+            }
+        }
+
+        return SCHEMAS;
+    }
+
+    @PreAuthorize("isAuthenticated()")
+    public String schema(final String schema) {
+        synchronized (MONITOR) {
+            if (SCHEMAS == null) {
+                init();
+            }
+        }
+
+        String found = SCHEMA_MAP.get(schema);
+        if (found == null) {
+            throw new NotFoundException("Schema " + schema);
+        }
+
+        return found;
+    }
+
+    @Override
+    protected AbstractBaseBean resolveReference(final Method method, final Object... args)
+            throws UnresolvedReferenceException {
+
+        throw new UnresolvedReferenceException();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java
index 894ba24..a5a1733 100644
--- a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java
+++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java
@@ -18,39 +18,14 @@
  */
 package org.apache.syncope.core.logic.init;
 
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.common.lib.PropertyUtils;
+import org.apache.syncope.common.lib.scim.types.SCIMEntitlement;
 import org.apache.syncope.core.persistence.api.SyncopeLoader;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
 import org.springframework.stereotype.Component;
 
 @Component
 public class SCIMLoader implements SyncopeLoader {
 
-    private static final Logger LOG = LoggerFactory.getLogger(SCIMLoader.class);
-
-    private static final String SCIMV2_LOGIC_PROPERTIES = "scimv2-logic.properties";
-
-    private static final String SCHEMAS = "schemas.json";
-
-    private int bulkMaxOperations = 0;
-
-    private int bulkMaxPayloadSize = 0;
-
-    private int filterMaxResults = 0;
-
-    private String schemas;
-
-    private final Map<String, String> schemaMap = new HashMap<>();
-
     @Override
     public Integer getPriority() {
         return 1000;
@@ -58,49 +33,7 @@ public class SCIMLoader implements SyncopeLoader {
 
     @Override
     public void load() {
-        Pair<Properties, String> init = PropertyUtils.read(getClass(), SCIMV2_LOGIC_PROPERTIES, "conf.directory");
-        Properties props = init.getLeft();
-
-        bulkMaxOperations = Integer.valueOf(props.getProperty("bulk.maxOperations"));
-        bulkMaxPayloadSize = Integer.valueOf(props.getProperty("bulk.maxPayloadSize"));
-        filterMaxResults = Integer.valueOf(props.getProperty("filter.maxResults"));
-
-        try {
-            ObjectMapper mapper = new ObjectMapper();
-            JsonNode tree = mapper.readTree(getClass().getResourceAsStream("/" + SCHEMAS));
-            if (!tree.isArray()) {
-                throw new IOException("JSON node is not a tree");
-            }
-
-            ArrayNode schemaArray = (ArrayNode) tree;
-            schemas = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(tree);
-
-            for (JsonNode schema : schemaArray) {
-                schemaMap.put(schema.get("id").asText(), mapper.writeValueAsString(schema));
-            }
-        } catch (IOException e) {
-            LOG.error("Could not parse the default schema definitions", e);
-        }
-    }
-
-    public int getBulkMaxOperations() {
-        return bulkMaxOperations;
-    }
-
-    public int getBulkMaxPayloadSize() {
-        return bulkMaxPayloadSize;
-    }
-
-    public int getFilterMaxResults() {
-        return filterMaxResults;
-    }
-
-    public String getSchemas() {
-        return schemas;
-    }
-
-    public String getSchema(final String schema) {
-        return schemaMap.get(schema);
+        EntitlementsHolder.getInstance().init(SCIMEntitlement.values());
     }
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMConfManager.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMConfManager.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMConfManager.java
new file mode 100644
index 0000000..ede870b
--- /dev/null
+++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMConfManager.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.logic.scim;
+
+import java.util.Date;
+import javax.ws.rs.core.MediaType;
+import org.apache.syncope.common.lib.scim.SCIMConf;
+import org.apache.syncope.common.lib.scim.types.SCIMEntitlement;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.PlainSchemaTO;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.core.logic.ConfigurationLogic;
+import org.apache.syncope.core.logic.SchemaLogic;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+import org.identityconnectors.common.Base64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SCIMConfManager {
+
+    protected static final Logger LOG = LoggerFactory.getLogger(SCIMConfManager.class);
+
+    @Autowired
+    private ConfigurationLogic configurationLogic;
+
+    @Autowired
+    private SchemaLogic schemaLogic;
+
+    @PreAuthorize("hasRole('" + SCIMEntitlement.SCIM_CONF_GET + "')")
+    public SCIMConf get() {
+        AttrTO confTO = null;
+        try {
+            confTO = configurationLogic.get(SCIMConf.KEY);
+        } catch (Exception e) {
+            LOG.error("{} not found, reverting to default", SCIMConf.KEY);
+        }
+
+        SCIMConf conf = null;
+        if (confTO != null) {
+            try {
+                conf = POJOHelper.deserialize(new String(Base64.decode(confTO.getValues().get(0))), SCIMConf.class);
+            } catch (Exception e) {
+                LOG.error("Could not deserialize, reverting to default", e);
+            }
+        }
+        if (conf == null) {
+            conf = new SCIMConf();
+            set(conf);
+        }
+
+        return conf;
+    }
+
+    @PreAuthorize("hasRole('" + SCIMEntitlement.SCIM_CONF_SET + "')")
+    public void set(final SCIMConf conf) {
+        try {
+            schemaLogic.read(SchemaType.PLAIN, SCIMConf.KEY);
+        } catch (NotFoundException e) {
+            PlainSchemaTO scimConf = new PlainSchemaTO();
+            scimConf.setKey(SCIMConf.KEY);
+            scimConf.setType(AttrSchemaType.Binary);
+            scimConf.setMimeType(MediaType.APPLICATION_JSON);
+            schemaLogic.create(SchemaType.PLAIN, scimConf);
+        }
+        conf.setLastChangeDate(new Date());
+
+        configurationLogic.set(new AttrTO.Builder().
+                schema(SCIMConf.KEY).value(Base64.encode(POJOHelper.serialize(conf).getBytes())).build());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/logic/src/main/resources/scimv2-logic.properties
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/resources/scimv2-logic.properties b/ext/scimv2/logic/src/main/resources/scimv2-logic.properties
deleted file mode 100644
index 2d85a37..0000000
--- a/ext/scimv2/logic/src/main/resources/scimv2-logic.properties
+++ /dev/null
@@ -1,21 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-conf.directory=${conf.directory}
-
-bulk.maxOperations=1000
-bulk.maxPayloadSize=1048576
-filter.maxResults=200

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/pom.xml
----------------------------------------------------------------------
diff --git a/ext/scimv2/pom.xml b/ext/scimv2/pom.xml
index bc62e00..5a55f49 100644
--- a/ext/scimv2/pom.xml
+++ b/ext/scimv2/pom.xml
@@ -38,9 +38,13 @@ under the License.
   </properties>
   
   <modules>
+    <module>common-lib</module>
+    <module>rest-api</module>
+    <module>rest-cxf</module>
     <module>scim-rest-api</module>
     <module>scim-rest-cxf</module>
     <module>logic</module>
+    <module>client-console</module>
   </modules>
 
 </project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/rest-api/pom.xml
----------------------------------------------------------------------
diff --git a/ext/scimv2/rest-api/pom.xml b/ext/scimv2/rest-api/pom.xml
new file mode 100644
index 0000000..7010846
--- /dev/null
+++ b/ext/scimv2/rest-api/pom.xml
@@ -0,0 +1,77 @@
+<?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.ext</groupId>
+    <artifactId>syncope-ext-scimv2</artifactId>
+    <version>2.1.0-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Ext: SCIMv2 REST API</name>
+  <description>Apache Syncope Ext: SCIMv2 REST API</description>
+  <groupId>org.apache.syncope.ext.scimv2</groupId>
+  <artifactId>syncope-ext-scimv2-rest-api</artifactId>
+  <packaging>jar</packaging>
+  
+  <properties>
+    <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.syncope.common</groupId>
+      <artifactId>syncope-common-rest-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-common-lib</artifactId>      
+      <version>${project.version}</version>
+    </dependency>    
+  </dependencies>
+
+  <build>
+    <plugins>
+      <!-- Generating javadoc JAR artifact for usage with CXF's WADL generator (for core) -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <inherited>true</inherited>
+        <executions>
+          <execution>
+            <id>attach-javadocs</id>
+            <goals>
+              <goal>jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SCIMConfService.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SCIMConfService.java b/ext/scimv2/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SCIMConfService.java
new file mode 100644
index 0000000..fdc4da3
--- /dev/null
+++ b/ext/scimv2/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SCIMConfService.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.rest.api.service;
+
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import org.apache.syncope.common.lib.scim.SCIMConf;
+
+/**
+ * REST operations for SCIM 2.0 configuration.
+ */
+@Path("scimv2conf")
+public interface SCIMConfService extends JAXRSService {
+
+    /**
+     * Reads SCIM configuration, generates empty if missing.
+     *
+     * @return SCIM configuration
+     */
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    SCIMConf get();
+
+    /**
+     * Sets SCIM configuration.
+     *
+     * @param conf SCIM configuration
+     */
+    @PUT
+    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    void set(@NotNull SCIMConf conf);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/rest-cxf/pom.xml
----------------------------------------------------------------------
diff --git a/ext/scimv2/rest-cxf/pom.xml b/ext/scimv2/rest-cxf/pom.xml
new file mode 100644
index 0000000..403f430
--- /dev/null
+++ b/ext/scimv2/rest-cxf/pom.xml
@@ -0,0 +1,72 @@
+<?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.ext</groupId>
+    <artifactId>syncope-ext-scimv2</artifactId>
+    <version>2.1.0-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Ext: SCIMv2 REST CXF</name>
+  <description>Apache Syncope Ext: SCIMv2 REST CXF</description>
+  <groupId>org.apache.syncope.ext.scimv2</groupId>
+  <artifactId>syncope-ext-scimv2-rest-cxf</artifactId>
+  <packaging>jar</packaging>
+  
+  <properties>
+    <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.syncope.core</groupId>
+      <artifactId>syncope-core-rest-cxf</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-rest-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-rest-api</artifactId>
+      <version>${project.version}</version>
+      <classifier>javadoc</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-logic</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SCIMConfServiceImpl.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SCIMConfServiceImpl.java b/ext/scimv2/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SCIMConfServiceImpl.java
new file mode 100644
index 0000000..223aca7
--- /dev/null
+++ b/ext/scimv2/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SCIMConfServiceImpl.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.core.rest.cxf.service;
+
+import org.apache.syncope.common.lib.scim.SCIMConf;
+import org.apache.syncope.common.rest.api.service.SCIMConfService;
+import org.apache.syncope.core.logic.scim.SCIMConfManager;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class SCIMConfServiceImpl extends AbstractServiceImpl implements SCIMConfService {
+
+    @Autowired
+    private SCIMConfManager manager;
+
+    @Override
+    public SCIMConf get() {
+        return manager.get();
+    }
+
+    @Override
+    public void set(final SCIMConf conf) {
+        manager.set(conf);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Display.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Display.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Display.java
deleted file mode 100644
index f79796c..0000000
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Display.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.ext.scimv2.api.data;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public class Display extends SCIMBean {
-
-    private static final long serialVersionUID = 5337055958765320091L;
-
-    private final String value;
-
-    private final String display;
-
-    @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
-    public Display(@JsonProperty("value") final String value, @JsonProperty("display") final String display) {
-        this.value = value;
-        this.display = display;
-    }
-
-    public String getValue() {
-        return value;
-    }
-
-    public String getDisplay() {
-        return display;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Reference.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Reference.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Reference.java
index d65f5e8..a00c793 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Reference.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Reference.java
@@ -20,18 +20,25 @@ package org.apache.syncope.ext.scimv2.api.data;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 
-abstract class Reference extends Display {
+abstract class Reference extends Value {
 
     private static final long serialVersionUID = -6190164044699376089L;
 
+    private final String display;
+
     @JsonProperty("$ref")
     private final String ref;
 
     Reference(final String value, final String display, final String ref) {
-        super(value, display);
+        super(value);
+        this.display = display;
         this.ref = ref;
     }
 
+    public String getDisplay() {
+        return display;
+    }
+
     public String getRef() {
         return ref;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMBean.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMBean.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMBean.java
index 95334cf..ca191be 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMBean.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMBean.java
@@ -21,7 +21,7 @@ package org.apache.syncope.ext.scimv2.api.data;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import java.io.Serializable;
 
-@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
 abstract class SCIMBean implements Serializable {
 
     private static final long serialVersionUID = 7604407251038024743L;

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMComplexValue.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMComplexValue.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMComplexValue.java
new file mode 100644
index 0000000..94c4320
--- /dev/null
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMComplexValue.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.ext.scimv2.api.data;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+public class SCIMComplexValue extends SCIMBean {
+
+    private static final long serialVersionUID = -3887211468327809832L;
+
+    private String value;
+
+    private String display;
+
+    private String type;
+
+    private boolean primary;
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(final String value) {
+        this.value = value;
+    }
+
+    public String getDisplay() {
+        return display;
+    }
+
+    public void setDisplay(final String display) {
+        this.display = display;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(final String type) {
+        this.type = type;
+    }
+
+    public boolean isPrimary() {
+        return primary;
+    }
+
+    public void setPrimary(final boolean primary) {
+        this.primary = primary;
+    }
+
+    @JsonIgnore
+    public boolean isEmpty() {
+        return value == null && display == null && type == null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMEnterpriseInfo.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMEnterpriseInfo.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMEnterpriseInfo.java
new file mode 100644
index 0000000..d419c09
--- /dev/null
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMEnterpriseInfo.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.ext.scimv2.api.data;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+public class SCIMEnterpriseInfo extends SCIMBean {
+
+    private static final long serialVersionUID = 5745005071861557082L;
+
+    private String employeeNumber;
+
+    private String costCenter;
+
+    private String organization;
+
+    private String division;
+
+    private String department;
+
+    private SCIMUserManager manager;
+
+    public String getEmployeeNumber() {
+        return employeeNumber;
+    }
+
+    public void setEmployeeNumber(final String employeeNumber) {
+        this.employeeNumber = employeeNumber;
+    }
+
+    public String getCostCenter() {
+        return costCenter;
+    }
+
+    public void setCostCenter(final String costCenter) {
+        this.costCenter = costCenter;
+    }
+
+    public String getOrganization() {
+        return organization;
+    }
+
+    public void setOrganization(final String organization) {
+        this.organization = organization;
+    }
+
+    public String getDivision() {
+        return division;
+    }
+
+    public void setDivision(final String division) {
+        this.division = division;
+    }
+
+    public String getDepartment() {
+        return department;
+    }
+
+    public void setDepartment(final String department) {
+        this.department = department;
+    }
+
+    public SCIMUserManager getManager() {
+        return manager;
+    }
+
+    public void setManager(final SCIMUserManager manager) {
+        this.manager = manager;
+    }
+
+    @JsonIgnore
+    public boolean isEmpty() {
+        return employeeNumber == null
+                && costCenter == null
+                && organization == null
+                && division == null
+                && department == null
+                && manager == null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUser.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUser.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUser.java
index c76c0f0..775b1ad 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUser.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUser.java
@@ -24,18 +24,61 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 import java.util.ArrayList;
 import java.util.List;
 
-@JsonPropertyOrder({ "schemas", "id", "externalId", "userName", "active", "groups", "roles", "meta" })
+@JsonPropertyOrder({ "schemas", "id", "externalId",
+    "userName", "password", "active",
+    "name", "displayName", "nickName", "profileUrl", "title", "userType", "preferredLanguage", "locale", "timezone",
+    "emails", "phoneNumbers", "ims", "photos", "addresses", "x509Certificates",
+    "groups", "entitlements", "roles",
+    "enterpriseInfo",
+    "meta" })
 public class SCIMUser extends SCIMResource {
 
     private static final long serialVersionUID = -2935466041674390279L;
 
     private final String userName;
 
+    private String password;
+
     private final boolean active;
 
+    private SCIMUserName name;
+
+    private String displayName;
+
+    private String nickName;
+
+    private String profileUrl;
+
+    private String title;
+
+    private String userType;
+
+    private String preferredLanguage;
+
+    private String locale;
+
+    private String timezone;
+
+    private final List<SCIMComplexValue> emails = new ArrayList<>();
+
+    private final List<SCIMComplexValue> phoneNumbers = new ArrayList<>();
+
+    private final List<SCIMComplexValue> ims = new ArrayList<>();
+
+    private final List<SCIMComplexValue> photos = new ArrayList<>();
+
+    private final List<SCIMUserAddress> addresses = new ArrayList<>();
+
+    private final List<Value> x509Certificates = new ArrayList<>();
+
     private final List<Group> groups = new ArrayList<>();
 
-    private final List<Display> roles = new ArrayList<>();
+    private final List<Value> entitlements = new ArrayList<>();
+
+    private final List<Value> roles = new ArrayList<>();
+
+    @JsonProperty("urn:ietf:params:scim:schemas:extension:enterprise:2.0:User")
+    private SCIMEnterpriseInfo enterpriseInfo;
 
     @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
     public SCIMUser(
@@ -54,16 +97,132 @@ public class SCIMUser extends SCIMResource {
         return userName;
     }
 
+    public void setPassword(final String password) {
+        this.password = password;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
     public boolean isActive() {
         return active;
     }
 
+    public SCIMUserName getName() {
+        return name;
+    }
+
+    public void setName(final SCIMUserName name) {
+        this.name = name;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public void setDisplayName(final String displayName) {
+        this.displayName = displayName;
+    }
+
+    public String getNickName() {
+        return nickName;
+    }
+
+    public void setNickName(final String nickName) {
+        this.nickName = nickName;
+    }
+
+    public String getProfileUrl() {
+        return profileUrl;
+    }
+
+    public void setProfileUrl(final String profileUrl) {
+        this.profileUrl = profileUrl;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(final String title) {
+        this.title = title;
+    }
+
+    public String getUserType() {
+        return userType;
+    }
+
+    public void setUserType(final String userType) {
+        this.userType = userType;
+    }
+
+    public String getPreferredLanguage() {
+        return preferredLanguage;
+    }
+
+    public void setPreferredLanguage(final String preferredLanguage) {
+        this.preferredLanguage = preferredLanguage;
+    }
+
+    public String getLocale() {
+        return locale;
+    }
+
+    public void setLocale(final String locale) {
+        this.locale = locale;
+    }
+
+    public String getTimezone() {
+        return timezone;
+    }
+
+    public void setTimezone(final String timezone) {
+        this.timezone = timezone;
+    }
+
+    public List<SCIMComplexValue> getEmails() {
+        return emails;
+    }
+
+    public List<SCIMComplexValue> getPhoneNumbers() {
+        return phoneNumbers;
+    }
+
+    public List<SCIMComplexValue> getIms() {
+        return ims;
+    }
+
+    public List<SCIMComplexValue> getPhotos() {
+        return photos;
+    }
+
+    public List<SCIMUserAddress> getAddresses() {
+        return addresses;
+    }
+
+    public List<Value> getX509Certificates() {
+        return x509Certificates;
+    }
+
     public List<Group> getGroups() {
         return groups;
     }
 
-    public List<Display> getRoles() {
+    public List<Value> getEntitlements() {
+        return entitlements;
+    }
+
+    public List<Value> getRoles() {
         return roles;
     }
 
+    public SCIMEnterpriseInfo getEnterpriseInfo() {
+        return enterpriseInfo;
+    }
+
+    public void setEnterpriseInfo(final SCIMEnterpriseInfo enterpriseInfo) {
+        this.enterpriseInfo = enterpriseInfo;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserAddress.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserAddress.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserAddress.java
new file mode 100644
index 0000000..3c1f0d9
--- /dev/null
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserAddress.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.ext.scimv2.api.data;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+public class SCIMUserAddress extends SCIMBean {
+
+    private static final long serialVersionUID = -7936040729842689890L;
+
+    private String formatted;
+
+    private String streetAddress;
+
+    private String locality;
+
+    private String region;
+
+    private String postalCode;
+
+    private String country;
+
+    private String type;
+
+    private boolean primary;
+
+    public String getFormatted() {
+        return formatted;
+    }
+
+    public void setFormatted(final String formatted) {
+        this.formatted = formatted;
+    }
+
+    public String getStreetAddress() {
+        return streetAddress;
+    }
+
+    public void setStreetAddress(final String streetAddress) {
+        this.streetAddress = streetAddress;
+    }
+
+    public String getLocality() {
+        return locality;
+    }
+
+    public void setLocality(final String locality) {
+        this.locality = locality;
+    }
+
+    public String getRegion() {
+        return region;
+    }
+
+    public void setRegion(final String region) {
+        this.region = region;
+    }
+
+    public String getPostalCode() {
+        return postalCode;
+    }
+
+    public void setPostalCode(final String postalCode) {
+        this.postalCode = postalCode;
+    }
+
+    public String getCountry() {
+        return country;
+    }
+
+    public void setCountry(final String country) {
+        this.country = country;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(final String type) {
+        this.type = type;
+    }
+
+    public boolean isPrimary() {
+        return primary;
+    }
+
+    public void setPrimary(final boolean primary) {
+        this.primary = primary;
+    }
+
+    @JsonIgnore
+    public boolean isEmpty() {
+        return formatted == null
+                && streetAddress == null
+                && locality == null
+                && region == null
+                && postalCode == null
+                && country == null
+                && type == null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserManager.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserManager.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserManager.java
new file mode 100644
index 0000000..c1294e9
--- /dev/null
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserManager.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.ext.scimv2.api.data;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class SCIMUserManager extends SCIMBean {
+
+    private static final long serialVersionUID = -4193118676994783252L;
+
+    private String value;
+
+    @JsonProperty("$ref")
+    private String ref;
+
+    private String displayName;
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(final String value) {
+        this.value = value;
+    }
+
+    public String getRef() {
+        return ref;
+    }
+
+    public void setRef(final String ref) {
+        this.ref = ref;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public void setDisplayName(final String displayName) {
+        this.displayName = displayName;
+    }
+
+    @JsonIgnore
+    public boolean isEmpty() {
+        return value == null && ref == null && displayName == null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserName.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserName.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserName.java
new file mode 100644
index 0000000..0293e95
--- /dev/null
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserName.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.ext.scimv2.api.data;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+public class SCIMUserName extends SCIMBean {
+
+    private static final long serialVersionUID = 5492302691746462480L;
+
+    private String formatted;
+
+    private String familyName;
+
+    private String givenName;
+
+    private String middleName;
+
+    private String honorificPrefix;
+
+    private String honorificSuffix;
+
+    public String getFormatted() {
+        return formatted;
+    }
+
+    public void setFormatted(final String formatted) {
+        this.formatted = formatted;
+    }
+
+    public String getFamilyName() {
+        return familyName;
+    }
+
+    public void setFamilyName(final String familyName) {
+        this.familyName = familyName;
+    }
+
+    public String getGivenName() {
+        return givenName;
+    }
+
+    public void setGivenName(final String givenName) {
+        this.givenName = givenName;
+    }
+
+    public String getMiddleName() {
+        return middleName;
+    }
+
+    public void setMiddleName(final String middleName) {
+        this.middleName = middleName;
+    }
+
+    public String getHonorificPrefix() {
+        return honorificPrefix;
+    }
+
+    public void setHonorificPrefix(final String honorificPrefix) {
+        this.honorificPrefix = honorificPrefix;
+    }
+
+    public String getHonorificSuffix() {
+        return honorificSuffix;
+    }
+
+    public void setHonorificSuffix(final String honorificSuffix) {
+        this.honorificSuffix = honorificSuffix;
+    }
+
+    @JsonIgnore
+    public boolean isEmpty() {
+        return formatted == null
+                && familyName == null
+                && givenName == null
+                && middleName == null
+                && honorificPrefix == null
+                && honorificSuffix == null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/ServiceProviderConfig.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/ServiceProviderConfig.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/ServiceProviderConfig.java
index 3014a6c..75eec0a 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/ServiceProviderConfig.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/ServiceProviderConfig.java
@@ -20,17 +20,22 @@ package org.apache.syncope.ext.scimv2.api.data;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import org.apache.syncope.ext.scimv2.api.type.Resource;
 
+@JsonPropertyOrder(
+        { "schemas", "patch", "bulk", "filter", "changePassword", "sort", "etag", "authenticationSchemes", "meta" })
 public class ServiceProviderConfig extends SCIMBean {
 
     private static final long serialVersionUID = 1027738509789460252L;
 
     private final List<String> schemas = Arrays.asList(Resource.ServiceProviderConfig.schema());
 
+    private final Meta meta;
+
     private final ConfigurationOption patch;
 
     private final BulkConfigurationOption bulk;
@@ -47,6 +52,7 @@ public class ServiceProviderConfig extends SCIMBean {
 
     @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
     public ServiceProviderConfig(
+            @JsonProperty("meta") final Meta meta,
             @JsonProperty("patch") final ConfigurationOption patch,
             @JsonProperty("bulk") final BulkConfigurationOption bulk,
             @JsonProperty("filter") final FilterConfigurationOption filter,
@@ -54,6 +60,7 @@ public class ServiceProviderConfig extends SCIMBean {
             @JsonProperty("sort") final ConfigurationOption sort,
             @JsonProperty("etag") final ConfigurationOption etag) {
 
+        this.meta = meta;
         this.patch = patch;
         this.bulk = bulk;
         this.filter = filter;
@@ -66,6 +73,10 @@ public class ServiceProviderConfig extends SCIMBean {
         return schemas;
     }
 
+    public Meta getMeta() {
+        return meta;
+    }
+
     public ConfigurationOption getPatch() {
         return patch;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Value.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Value.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Value.java
new file mode 100644
index 0000000..543f000
--- /dev/null
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Value.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.ext.scimv2.api.data;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Value extends SCIMBean {
+
+    private static final long serialVersionUID = 5337055958765320091L;
+
+    private final String value;
+
+    @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+    public Value(@JsonProperty("value") final String value) {
+        this.value = value;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/GroupService.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/GroupService.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/GroupService.java
index 8881ec8..196572e 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/GroupService.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/GroupService.java
@@ -33,7 +33,7 @@ import org.apache.syncope.ext.scimv2.api.SCIMConstants;
 import org.apache.syncope.ext.scimv2.api.data.SCIMGroup;
 
 @Path("v2/Groups")
-public interface GroupService extends SCIMService<SCIMGroup> {
+public interface GroupService extends SearchService<SCIMGroup> {
 
     @POST
     @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/RootService.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/RootService.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/RootService.java
deleted file mode 100644
index 6e9b201..0000000
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/RootService.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.ext.scimv2.api.service;
-
-import java.util.List;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Response;
-import org.apache.syncope.ext.scimv2.api.SCIMConstants;
-import org.apache.syncope.ext.scimv2.api.data.ResourceType;
-import org.apache.syncope.ext.scimv2.api.data.SCIMResource;
-import org.apache.syncope.ext.scimv2.api.data.ServiceProviderConfig;
-
-@Path("v2")
-public interface RootService extends SCIMService<SCIMResource> {
-
-    @GET
-    @Path("ServiceProviderConfig")
-    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
-    ServiceProviderConfig serviceProviderConfig();
-
-    @GET
-    @Path("ResourceTypes")
-    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
-    List<ResourceType> resourceTypes();
-
-    @GET
-    @Path("ResourceTypes/{type}")
-    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
-    ResourceType resourceType(@PathParam("type") String type);
-
-    @GET
-    @Path("Schemas")
-    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
-    Response schemas();
-
-    @GET
-    @Path("Schemas/{schema}")
-    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
-    Response schema(@PathParam("schema") String schema);
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SCIMService.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SCIMService.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SCIMService.java
index 1b2fd3f..6064747 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SCIMService.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SCIMService.java
@@ -20,22 +20,40 @@ package org.apache.syncope.ext.scimv2.api.service;
 
 import java.util.List;
 import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
 import org.apache.syncope.ext.scimv2.api.SCIMConstants;
-import org.apache.syncope.ext.scimv2.api.data.ListResponse;
+import org.apache.syncope.ext.scimv2.api.data.ResourceType;
 import org.apache.syncope.ext.scimv2.api.data.SCIMResource;
-import org.apache.syncope.ext.scimv2.api.type.SortOrder;
+import org.apache.syncope.ext.scimv2.api.data.ServiceProviderConfig;
 
-public interface SCIMService<R extends SCIMResource> {
+@Path("v2")
+public interface SCIMService extends SearchService<SCIMResource> {
 
     @GET
+    @Path("ServiceProviderConfig")
     @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
-    ListResponse<R> search(
-            @QueryParam("startIndex") Integer startIndex,
-            @QueryParam("count") Integer count,
-            @QueryParam("filter") String filter,
-            @QueryParam("sortBy") String sortBy,
-            @QueryParam("sortOrder") SortOrder sortOrder,
-            @QueryParam("attributes") List<String> attributes);
+    ServiceProviderConfig serviceProviderConfig();
+
+    @GET
+    @Path("ResourceTypes")
+    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
+    List<ResourceType> resourceTypes();
+
+    @GET
+    @Path("ResourceTypes/{type}")
+    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
+    ResourceType resourceType(@PathParam("type") String type);
+
+    @GET
+    @Path("Schemas")
+    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
+    Response schemas();
+
+    @GET
+    @Path("Schemas/{schema}")
+    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
+    Response schema(@PathParam("schema") String schema);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SearchService.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SearchService.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SearchService.java
new file mode 100644
index 0000000..fcd4789
--- /dev/null
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SearchService.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.ext.scimv2.api.service;
+
+import java.util.List;
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import org.apache.syncope.ext.scimv2.api.SCIMConstants;
+import org.apache.syncope.ext.scimv2.api.data.ListResponse;
+import org.apache.syncope.ext.scimv2.api.data.SCIMResource;
+import org.apache.syncope.ext.scimv2.api.type.SortOrder;
+
+public interface SearchService<R extends SCIMResource> {
+
+    @GET
+    @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })
+    ListResponse<R> search(
+            @QueryParam("startIndex") Integer startIndex,
+            @QueryParam("count") Integer count,
+            @QueryParam("filter") String filter,
+            @QueryParam("sortBy") String sortBy,
+            @QueryParam("sortOrder") SortOrder sortOrder,
+            @QueryParam("attributes") List<String> attributes);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/UserService.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/UserService.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/UserService.java
index 8003b66..1135650 100644
--- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/UserService.java
+++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/UserService.java
@@ -33,7 +33,7 @@ import org.apache.syncope.ext.scimv2.api.SCIMConstants;
 import org.apache.syncope.ext.scimv2.api.data.SCIMUser;
 
 @Path("v2/Users")
-public interface UserService extends SCIMService<SCIMUser> {
+public interface UserService extends SearchService<SCIMUser> {
 
     @POST
     @Produces({ SCIMConstants.APPLICATION_SCIM_JSON })

http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/AddETagFilter.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/AddETagFilter.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/AddETagFilter.java
index 498ea95..d2c76a8 100644
--- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/AddETagFilter.java
+++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/AddETagFilter.java
@@ -46,7 +46,7 @@ public class AddETagFilter implements ContainerResponseFilter {
                 if (lastModified != null) {
                     String etagValue = String.valueOf(lastModified.getTime());
                     if (StringUtils.isNotBlank(etagValue)) {
-                        resCtx.getHeaders().add(HttpHeaders.ETAG, new EntityTag(etagValue).toString());
+                        resCtx.getHeaders().add(HttpHeaders.ETAG, new EntityTag(etagValue, true).toString());
                     }
                 }
             }


[4/6] syncope git commit: [SYNCOPE-152] SCIM configuration including attribute mapping + console extension

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java
deleted file mode 100644
index f2361d2..0000000
--- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractSCIMService.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.ext.scimv2.cxf.service;
-
-import java.util.Collections;
-import java.util.List;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.UriInfo;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.tuple.Pair;
-import org.apache.cxf.jaxrs.ext.MessageContext;
-import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.to.GroupTO;
-import org.apache.syncope.common.lib.to.MembershipTO;
-import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.syncope.core.logic.AbstractAnyLogic;
-import org.apache.syncope.core.logic.GroupLogic;
-import org.apache.syncope.core.logic.UserLogic;
-import org.apache.syncope.core.logic.scim.SearchCondConverter;
-import org.apache.syncope.core.persistence.api.dao.AnyDAO;
-import org.apache.syncope.core.persistence.api.dao.search.MembershipCond;
-import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
-import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
-import org.apache.syncope.core.spring.ApplicationContextProvider;
-import org.apache.syncope.ext.scimv2.api.data.Display;
-import org.apache.syncope.ext.scimv2.api.data.Group;
-import org.apache.syncope.ext.scimv2.api.data.ListResponse;
-import org.apache.syncope.ext.scimv2.api.data.Member;
-import org.apache.syncope.ext.scimv2.api.data.Meta;
-import org.apache.syncope.ext.scimv2.api.data.SCIMGroup;
-import org.apache.syncope.ext.scimv2.api.data.SCIMResource;
-import org.apache.syncope.ext.scimv2.api.data.SCIMUser;
-import org.apache.syncope.ext.scimv2.api.service.SCIMService;
-import org.apache.syncope.ext.scimv2.api.type.Function;
-import org.apache.syncope.ext.scimv2.api.type.Resource;
-import org.apache.syncope.ext.scimv2.api.type.SortOrder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-abstract class AbstractSCIMService<R extends SCIMResource> implements SCIMService<R> {
-
-    protected static final Logger LOG = LoggerFactory.getLogger(AbstractSCIMService.class);
-
-    @Context
-    protected UriInfo uriInfo;
-
-    @Context
-    protected MessageContext messageContext;
-
-    private UserLogic userLogic;
-
-    private GroupLogic groupLogic;
-
-    protected UserLogic userLogic() {
-        synchronized (this) {
-            if (userLogic == null) {
-                userLogic = ApplicationContextProvider.getApplicationContext().getBean(UserLogic.class);
-            }
-        }
-        return userLogic;
-    }
-
-    protected GroupLogic groupLogic() {
-        synchronized (this) {
-            if (groupLogic == null) {
-                groupLogic = ApplicationContextProvider.getApplicationContext().getBean(GroupLogic.class);
-            }
-        }
-        return groupLogic;
-    }
-
-    protected AbstractAnyLogic<?, ?> anyLogic(final Resource type) {
-        switch (type) {
-            case User:
-                return userLogic();
-
-            case Group:
-                return groupLogic();
-
-            default:
-                throw new UnsupportedOperationException();
-        }
-    }
-
-    protected SCIMUser toSCIMUser(final UserTO userTO, final String location) {
-        SCIMUser user = new SCIMUser(
-                userTO.getKey(),
-                Collections.singletonList(Resource.User.schema()),
-                new Meta(
-                        Resource.User,
-                        userTO.getCreationDate(),
-                        userTO.getLastChangeDate() == null
-                        ? userTO.getCreationDate() : userTO.getLastChangeDate(),
-                        userTO.getETagValue(),
-                        location),
-                userTO.getUsername(),
-                !userTO.isSuspended());
-
-        for (MembershipTO membership : userTO.getMemberships()) {
-            user.getGroups().add(new Group(
-                    membership.getGroupKey(),
-                    StringUtils.substringBefore(location, "/Users") + "/Groups/" + membership.getGroupKey(),
-                    membership.getGroupName(),
-                    Function.direct));
-        }
-        for (MembershipTO membership : userTO.getDynMemberships()) {
-            user.getGroups().add(new Group(
-                    membership.getGroupKey(),
-                    StringUtils.substringBefore(location, "/Users") + "/Groups/" + membership.getGroupKey(),
-                    membership.getGroupName(),
-                    Function.indirect));
-        }
-
-        for (String role : userTO.getRoles()) {
-            user.getRoles().add(new Display(role, null));
-        }
-
-        return user;
-    }
-
-    protected SCIMGroup toSCIMGroup(final GroupTO groupTO, final String location) {
-        SCIMGroup group = new SCIMGroup(
-                groupTO.getKey(),
-                Collections.singletonList(Resource.Group.schema()),
-                new Meta(
-                        Resource.Group,
-                        groupTO.getCreationDate(),
-                        groupTO.getLastChangeDate() == null
-                        ? groupTO.getCreationDate() : groupTO.getLastChangeDate(),
-                        groupTO.getETagValue(),
-                        location),
-                groupTO.getName());
-
-        MembershipCond membCond = new MembershipCond();
-        membCond.setGroup(groupTO.getKey());
-        SearchCond searchCond = SearchCond.getLeafCond(membCond);
-
-        int count = userLogic().
-                search(searchCond, 1, 1, Collections.<OrderByClause>emptyList(), SyncopeConstants.ROOT_REALM, false).
-                getLeft();
-
-        for (int page = 1; page <= (count / AnyDAO.DEFAULT_PAGE_SIZE) + 1; page++) {
-            List<UserTO> users = userLogic().search(
-                    searchCond,
-                    page,
-                    AnyDAO.DEFAULT_PAGE_SIZE,
-                    Collections.<OrderByClause>emptyList(),
-                    SyncopeConstants.ROOT_REALM,
-                    false).
-                    getRight();
-            for (UserTO userTO : users) {
-                group.getMembers().add(new Member(
-                        userTO.getKey(),
-                        StringUtils.substringBefore(location, "/Groups") + "/Users/" + userTO.getKey(),
-                        userTO.getUsername(),
-                        Resource.User));
-            }
-        }
-
-        return group;
-    }
-
-    @SuppressWarnings("unchecked")
-    protected ListResponse<R> doSearch(
-            final Resource type,
-            final Integer startIndex,
-            final Integer count,
-            final String filter,
-            final String sortBy,
-            final SortOrder sortOrder,
-            final List<String> attributes) {
-
-        if (type == null) {
-            throw new UnsupportedOperationException();
-        }
-
-        Pair<Integer, ? extends List<? extends AnyTO>> result = anyLogic(type).search(
-                StringUtils.isBlank(filter) ? null : SearchCondConverter.convert(filter),
-                startIndex == null || startIndex <= 1 ? 1 : (startIndex / AnyDAO.DEFAULT_PAGE_SIZE) + 1,
-                AnyDAO.DEFAULT_PAGE_SIZE,
-                Collections.<OrderByClause>emptyList(),
-                SyncopeConstants.ROOT_REALM,
-                false);
-
-        ListResponse<R> response = new ListResponse<>(
-                result.getLeft(), startIndex == null || startIndex <= 1 ? 1 : startIndex, AnyDAO.DEFAULT_PAGE_SIZE);
-
-        for (AnyTO anyTO : result.getRight()) {
-            SCIMResource resource = null;
-            if (anyTO instanceof UserTO) {
-                resource = toSCIMUser(
-                        (UserTO) anyTO,
-                        uriInfo.getAbsolutePathBuilder().path(anyTO.getKey()).build().toASCIIString());
-            } else if (anyTO instanceof GroupTO) {
-                resource = toSCIMGroup(
-                        (GroupTO) anyTO,
-                        uriInfo.getAbsolutePathBuilder().path(anyTO.getKey()).build().toASCIIString());
-            }
-
-            if (resource != null) {
-                response.getResources().add((R) resource);
-            }
-        }
-
-        return response;
-    }
-
-    @Override
-    public ListResponse<R> search(
-            final Integer startIndex,
-            final Integer count,
-            final String filter,
-            final String sortBy,
-            final SortOrder sortOrder,
-            final List<String> attributes) {
-
-        return doSearch(null, startIndex, count, filter, sortBy, sortOrder, attributes);
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractService.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractService.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractService.java
new file mode 100644
index 0000000..5eeca49
--- /dev/null
+++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractService.java
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.ext.scimv2.cxf.service;
+
+import java.util.Collections;
+import java.util.List;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.cxf.jaxrs.ext.MessageContext;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.core.logic.AbstractAnyLogic;
+import org.apache.syncope.core.logic.GroupLogic;
+import org.apache.syncope.core.logic.SCIMDataBinder;
+import org.apache.syncope.core.logic.UserLogic;
+import org.apache.syncope.core.logic.scim.SearchCondConverter;
+import org.apache.syncope.core.persistence.api.dao.AnyDAO;
+import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
+import org.apache.syncope.ext.scimv2.api.data.ListResponse;
+import org.apache.syncope.ext.scimv2.api.data.SCIMResource;
+import org.apache.syncope.ext.scimv2.api.type.Resource;
+import org.apache.syncope.ext.scimv2.api.type.SortOrder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.syncope.ext.scimv2.api.service.SearchService;
+
+abstract class AbstractService<R extends SCIMResource> implements SearchService<R> {
+
+    protected static final Logger LOG = LoggerFactory.getLogger(AbstractService.class);
+
+    @Context
+    protected UriInfo uriInfo;
+
+    @Context
+    protected MessageContext messageContext;
+
+    private UserLogic userLogic;
+
+    private GroupLogic groupLogic;
+
+    private SCIMDataBinder binder;
+
+    protected UserLogic userLogic() {
+        synchronized (this) {
+            if (userLogic == null) {
+                userLogic = ApplicationContextProvider.getApplicationContext().getBean(UserLogic.class);
+            }
+        }
+        return userLogic;
+    }
+
+    protected GroupLogic groupLogic() {
+        synchronized (this) {
+            if (groupLogic == null) {
+                groupLogic = ApplicationContextProvider.getApplicationContext().getBean(GroupLogic.class);
+            }
+        }
+        return groupLogic;
+    }
+
+    protected SCIMDataBinder binder() {
+        synchronized (this) {
+            if (binder == null) {
+                binder = ApplicationContextProvider.getApplicationContext().getBean(SCIMDataBinder.class);
+            }
+        }
+        return binder;
+    }
+
+    protected AbstractAnyLogic<?, ?> anyLogic(final Resource type) {
+        switch (type) {
+            case User:
+                return userLogic();
+
+            case Group:
+                return groupLogic();
+
+            default:
+                throw new UnsupportedOperationException();
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    protected ListResponse<R> doSearch(
+            final Resource type,
+            final Integer startIndex,
+            final Integer count,
+            final String filter,
+            final String sortBy,
+            final SortOrder sortOrder,
+            final List<String> attributes) {
+
+        if (type == null) {
+            throw new UnsupportedOperationException();
+        }
+
+        Pair<Integer, ? extends List<? extends AnyTO>> result = anyLogic(type).search(
+                StringUtils.isBlank(filter) ? null : SearchCondConverter.convert(filter),
+                startIndex == null || startIndex <= 1 ? 1 : (startIndex / AnyDAO.DEFAULT_PAGE_SIZE) + 1,
+                AnyDAO.DEFAULT_PAGE_SIZE,
+                Collections.<OrderByClause>emptyList(),
+                SyncopeConstants.ROOT_REALM,
+                false);
+
+        ListResponse<R> response = new ListResponse<>(
+                result.getLeft(), startIndex == null || startIndex <= 1 ? 1 : startIndex, AnyDAO.DEFAULT_PAGE_SIZE);
+
+        for (AnyTO anyTO : result.getRight()) {
+            SCIMResource resource = null;
+            if (anyTO instanceof UserTO) {
+                resource = binder().toSCIMUser(
+                        (UserTO) anyTO,
+                        uriInfo.getAbsolutePathBuilder().path(anyTO.getKey()).build().toASCIIString());
+            } else if (anyTO instanceof GroupTO) {
+                resource = binder().toSCIMGroup(
+                        (GroupTO) anyTO,
+                        uriInfo.getAbsolutePathBuilder().path(anyTO.getKey()).build().toASCIIString());
+            }
+
+            if (resource != null) {
+                response.getResources().add((R) resource);
+            }
+        }
+
+        return response;
+    }
+
+    @Override
+    public ListResponse<R> search(
+            final Integer startIndex,
+            final Integer count,
+            final String filter,
+            final String sortBy,
+            final SortOrder sortOrder,
+            final List<String> attributes) {
+
+        return doSearch(null, startIndex, count, filter, sortBy, sortOrder, attributes);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java
index 85b9198..d03b57c 100644
--- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java
+++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java
@@ -27,7 +27,7 @@ import org.apache.syncope.ext.scimv2.api.service.GroupService;
 import org.apache.syncope.ext.scimv2.api.type.Resource;
 import org.apache.syncope.ext.scimv2.api.type.SortOrder;
 
-public class GroupServiceImpl extends AbstractSCIMService<SCIMGroup> implements GroupService {
+public class GroupServiceImpl extends AbstractService<SCIMGroup> implements GroupService {
 
     @Override
     public Response create() {
@@ -38,7 +38,7 @@ public class GroupServiceImpl extends AbstractSCIMService<SCIMGroup> implements
 
     @Override
     public SCIMGroup read(final String id) {
-        return toSCIMGroup(groupLogic().read(id), uriInfo.getAbsolutePathBuilder().build().toASCIIString());
+        return binder().toSCIMGroup(groupLogic().read(id), uriInfo.getAbsolutePathBuilder().build().toASCIIString());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/RootServiceImpl.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/RootServiceImpl.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/RootServiceImpl.java
deleted file mode 100644
index 6038f2b..0000000
--- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/RootServiceImpl.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.ext.scimv2.cxf.service;
-
-import java.util.List;
-import javax.ws.rs.core.Response;
-import org.apache.syncope.core.logic.RootLogic;
-import org.apache.syncope.core.spring.ApplicationContextProvider;
-import org.apache.syncope.ext.scimv2.api.data.ResourceType;
-import org.apache.syncope.ext.scimv2.api.data.SCIMResource;
-import org.apache.syncope.ext.scimv2.api.data.ServiceProviderConfig;
-import org.apache.syncope.ext.scimv2.api.service.RootService;
-
-public class RootServiceImpl extends AbstractSCIMService<SCIMResource> implements RootService {
-
-    private RootLogic rootLogic;
-
-    protected RootLogic rootLogic() {
-        synchronized (this) {
-            if (rootLogic == null) {
-                rootLogic = ApplicationContextProvider.getApplicationContext().getBean(RootLogic.class);
-            }
-        }
-        return rootLogic;
-    }
-
-    @Override
-    public ServiceProviderConfig serviceProviderConfig() {
-        return rootLogic().serviceProviderConfig();
-    }
-
-    @Override
-    public List<ResourceType> resourceTypes() {
-        return rootLogic().resourceTypes(uriInfo.getAbsolutePathBuilder());
-    }
-
-    @Override
-    public ResourceType resourceType(final String type) {
-        return rootLogic().resourceType(uriInfo.getAbsolutePathBuilder(), type);
-    }
-
-    @Override
-    public Response schemas() {
-        return Response.ok(rootLogic().schemas()).build();
-    }
-
-    @Override
-    public Response schema(final String schema) {
-        return Response.ok(rootLogic().schema(schema)).build();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMServiceImpl.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMServiceImpl.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMServiceImpl.java
new file mode 100644
index 0000000..65e4ad1
--- /dev/null
+++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/SCIMServiceImpl.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.ext.scimv2.cxf.service;
+
+import java.util.List;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.core.logic.SCIMLogic;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
+import org.apache.syncope.ext.scimv2.api.data.ResourceType;
+import org.apache.syncope.ext.scimv2.api.data.SCIMResource;
+import org.apache.syncope.ext.scimv2.api.data.ServiceProviderConfig;
+import org.apache.syncope.ext.scimv2.api.service.SCIMService;
+
+public class SCIMServiceImpl extends AbstractService<SCIMResource> implements SCIMService {
+
+    private SCIMLogic scimLogic;
+
+    private SCIMLogic scimLogic() {
+        synchronized (this) {
+            if (scimLogic == null) {
+                scimLogic = ApplicationContextProvider.getApplicationContext().getBean(SCIMLogic.class);
+            }
+        }
+        return scimLogic;
+    }
+
+    @Override
+    public ServiceProviderConfig serviceProviderConfig() {
+        return scimLogic().serviceProviderConfig(uriInfo.getAbsolutePathBuilder());
+    }
+
+    @Override
+    public List<ResourceType> resourceTypes() {
+        return scimLogic().resourceTypes(uriInfo.getAbsolutePathBuilder());
+    }
+
+    @Override
+    public ResourceType resourceType(final String type) {
+        return scimLogic().resourceType(uriInfo.getAbsolutePathBuilder(), type);
+    }
+
+    @Override
+    public Response schemas() {
+        return Response.ok(scimLogic().schemas()).build();
+    }
+
+    @Override
+    public Response schema(final String schema) {
+        return Response.ok(scimLogic().schema(schema)).build();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/UserServiceImpl.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/UserServiceImpl.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/UserServiceImpl.java
index c12ed6c..67b9b47 100644
--- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/UserServiceImpl.java
+++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/UserServiceImpl.java
@@ -27,7 +27,7 @@ import org.apache.syncope.ext.scimv2.api.service.UserService;
 import org.apache.syncope.ext.scimv2.api.type.Resource;
 import org.apache.syncope.ext.scimv2.api.type.SortOrder;
 
-public class UserServiceImpl extends AbstractSCIMService<SCIMUser> implements UserService {
+public class UserServiceImpl extends AbstractService<SCIMUser> implements UserService {
 
     @Override
     public Response create() {
@@ -38,7 +38,7 @@ public class UserServiceImpl extends AbstractSCIMService<SCIMUser> implements Us
 
     @Override
     public SCIMUser read(final String id) {
-        return toSCIMUser(userLogic().read(id), uriInfo.getAbsolutePathBuilder().build().toASCIIString());
+        return binder().toSCIMUser(userLogic().read(id), uriInfo.getAbsolutePathBuilder().build().toASCIIString());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/fit/console-reference/pom.xml
----------------------------------------------------------------------
diff --git a/fit/console-reference/pom.xml b/fit/console-reference/pom.xml
index 5e2e207..f0871ef 100644
--- a/fit/console-reference/pom.xml
+++ b/fit/console-reference/pom.xml
@@ -69,6 +69,12 @@ under the License.
     </dependency>
     
     <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-client-console</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
     </dependency>

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/fit/console-reference/src/test/resources/rebel.xml
----------------------------------------------------------------------
diff --git a/fit/console-reference/src/test/resources/rebel.xml b/fit/console-reference/src/test/resources/rebel.xml
index f1189d5..cfd69c9 100644
--- a/fit/console-reference/src/test/resources/rebel.xml
+++ b/fit/console-reference/src/test/resources/rebel.xml
@@ -32,6 +32,8 @@ under the License.
     </dir>
     <dir name="${basedir}/../../ext/saml2sp/client-console/target/classes">
     </dir>
+    <dir name="${basedir}/../../ext/scimv2/client-console/target/classes">
+    </dir>
   </classpath>
 
   <web>
@@ -51,6 +53,10 @@ under the License.
       <dir name="${basedir}/../../ext/saml2sp/client-console/target/classes">
       </dir>
     </link>
+    <link target="/">
+      <dir name="${basedir}/../../ext/scimv2/client-console/target/classes">
+      </dir>
+    </link>
   </web>
 
 </application>

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/fit/core-reference/pom.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/pom.xml b/fit/core-reference/pom.xml
index 87348ff..80ed2e6 100644
--- a/fit/core-reference/pom.xml
+++ b/fit/core-reference/pom.xml
@@ -165,7 +165,25 @@ under the License.
       <artifactId>syncope-ext-saml2sp-client-console</artifactId>
       <version>${project.version}</version>
       <scope>test</scope>
-    </dependency>  
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-rest-cxf</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-scim-rest-cxf</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-client-console</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-test</artifactId>
@@ -1052,6 +1070,11 @@ under the License.
         
         <dependency>
           <groupId>org.apache.syncope.ext.scimv2</groupId>
+          <artifactId>syncope-ext-scimv2-rest-cxf</artifactId>
+          <version>${project.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.syncope.ext.scimv2</groupId>
           <artifactId>syncope-ext-scimv2-scim-rest-cxf</artifactId>
           <version>${project.version}</version>
         </dependency>

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/fit/core-reference/src/main/resources/all/scimv2-logic.properties
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/all/scimv2-logic.properties b/fit/core-reference/src/main/resources/all/scimv2-logic.properties
deleted file mode 100644
index 2d85a37..0000000
--- a/fit/core-reference/src/main/resources/all/scimv2-logic.properties
+++ /dev/null
@@ -1,21 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-conf.directory=${conf.directory}
-
-bulk.maxOperations=1000
-bulk.maxPayloadSize=1048576
-filter.maxResults=200

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
index 9c77fd5..938de9c 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
@@ -89,6 +89,7 @@ import org.apache.syncope.common.rest.api.service.ResourceHistoryService;
 import org.apache.syncope.common.rest.api.service.RoleService;
 import org.apache.syncope.common.rest.api.service.SAML2IdPService;
 import org.apache.syncope.common.rest.api.service.SAML2SPService;
+import org.apache.syncope.common.rest.api.service.SCIMConfService;
 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;
@@ -243,6 +244,8 @@ public abstract class AbstractITCase {
 
     protected static SAML2IdPService saml2IdPService;
 
+    protected static SCIMConfService scimConfService;
+
     @BeforeClass
     public static void securitySetup() {
         InputStream propStream = null;
@@ -310,6 +313,7 @@ public abstract class AbstractITCase {
         camelRouteService = adminClient.getService(CamelRouteService.class);
         saml2SpService = adminClient.getService(SAML2SPService.class);
         saml2IdPService = adminClient.getService(SAML2IdPService.class);
+        scimConfService = adminClient.getService(SCIMConfService.class);
     }
 
     protected static String getUUIDString() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
index d7e19a2..cabe7f8 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java
@@ -21,6 +21,7 @@ package org.apache.syncope.fit.core;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import com.fasterxml.jackson.databind.node.ArrayNode;
@@ -36,6 +37,8 @@ import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.scim.SCIMConf;
+import org.apache.syncope.common.lib.scim.SCIMUserConf;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.ext.scimv2.api.SCIMConstants;
@@ -154,6 +157,34 @@ public class SCIMITCase extends AbstractITCase {
     }
 
     @Test
+    public void conf() {
+        Assume.assumeTrue(SCIMDetector.isSCIMAvailable(webClient()));
+
+        SCIMConf conf = scimConfService.get();
+        assertNotNull(conf);
+
+        SCIMUserConf userConf = conf.getUserConf();
+        if (userConf == null) {
+            userConf = new SCIMUserConf();
+            conf.setUserConf(userConf);
+        }
+        assertNull(userConf.getDisplayName());
+        userConf.setDisplayName("cn");
+
+        scimConfService.set(conf);
+
+        Response response = webClient().path("Users").path("1417acbe-cbf6-4277-9372-e75e04f97000").get();
+        assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+        assertEquals(
+                SCIMConstants.APPLICATION_SCIM_JSON,
+                StringUtils.substringBefore(response.getHeaderString(HttpHeaders.CONTENT_TYPE), ";"));
+
+        SCIMUser user = response.readEntity(SCIMUser.class);
+        assertNotNull(user);
+        assertEquals("Rossini, Gioacchino", user.getDisplayName());
+    }
+
+    @Test
     public void list() throws IOException {
         Assume.assumeTrue(SCIMDetector.isSCIMAvailable(webClient()));
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/fit/core-reference/src/test/resources/rebel.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/rebel.xml b/fit/core-reference/src/test/resources/rebel.xml
index 68f5fb1..e740552 100644
--- a/fit/core-reference/src/test/resources/rebel.xml
+++ b/fit/core-reference/src/test/resources/rebel.xml
@@ -91,6 +91,12 @@ under the License.
     </dir>
     <dir name="${basedir}/../../ext/elasticsearch/persistence-jpa/target/classes">
     </dir>
+    <dir name="${basedir}/../../ext/scimv2/common-lib/target/classes">
+    </dir>
+    <dir name="${basedir}/../../ext/scimv2/rest-api/target/classes">
+    </dir>
+    <dir name="${basedir}/../../ext/scimv2/rest-cxf/target/classes">
+    </dir>
     <dir name="${basedir}/../../ext/scimv2/scim-rest-api/target/classes">
     </dir>
     <dir name="${basedir}/../../ext/scimv2/scim-rest-cxf/target/classes">


[6/6] syncope git commit: [SYNCOPE-152] SCIM configuration including attribute mapping + console extension

Posted by il...@apache.org.
[SYNCOPE-152] SCIM configuration including attribute mapping + console extension


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

Branch: refs/heads/2_0_X
Commit: 1aa7bcaff595e65abb42c9e9397fa2feec083e21
Parents: 460bd26
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Tue Nov 14 16:54:25 2017 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Tue Nov 14 17:24:12 2017 +0100

----------------------------------------------------------------------
 .../archetype-resources/console/pom.xml         |   6 +
 .../resources/archetype-resources/core/pom.xml  |  11 +
 .../panels/ParametersDirectoryPanel.java        |   2 +-
 .../console/panels/RoleDirectoryPanel.java      |   2 +-
 ext/scimv2/client-console/pom.xml               |  78 ++++
 .../syncope/client/console/pages/SCIMConf.java  | 137 +++++++
 .../client/console/rest/SCIMConfRestClient.java |  35 ++
 .../syncope/client/console/pages/SCIMConf.html  |  41 ++
 .../client/console/pages/SCIMConf.properties    |  17 +
 .../client/console/pages/SCIMConf_it.properties |  17 +
 .../console/pages/SCIMConf_pt_BR.properties     |  17 +
 .../client/console/pages/SCIMConf_ru.properties |  17 +
 ext/scimv2/common-lib/pom.xml                   |  56 +++
 .../common/lib/scim/SCIMComplexConf.java        |  67 ++++
 .../syncope/common/lib/scim/SCIMConf.java       | 126 ++++++
 .../common/lib/scim/SCIMEnterpriseUserConf.java |  87 ++++
 .../common/lib/scim/SCIMManagerConf.java        |  47 +++
 .../common/lib/scim/SCIMUserAddressConf.java    | 107 +++++
 .../syncope/common/lib/scim/SCIMUserConf.java   | 159 ++++++++
 .../common/lib/scim/SCIMUserNameConf.java       |  87 ++++
 .../lib/scim/types/AddressCanonicalType.java    |  26 ++
 .../lib/scim/types/EmailCanonicalType.java      |  26 ++
 .../common/lib/scim/types/IMCanonicalType.java  |  31 ++
 .../scim/types/PhoneNumberCanonicalType.java    |  29 ++
 .../lib/scim/types/PhotoCanonicalType.java      |  25 ++
 .../common/lib/scim/types/SCIMEntitlement.java  |  52 +++
 ext/scimv2/logic/pom.xml                        |   6 +
 .../apache/syncope/core/logic/RootLogic.java    | 143 -------
 .../syncope/core/logic/SCIMDataBinder.java      | 397 +++++++++++++++++++
 .../apache/syncope/core/logic/SCIMLogic.java    | 198 +++++++++
 .../syncope/core/logic/init/SCIMLoader.java     |  73 +---
 .../core/logic/scim/SCIMConfManager.java        |  93 +++++
 .../src/main/resources/scimv2-logic.properties  |  21 -
 ext/scimv2/pom.xml                              |   4 +
 ext/scimv2/rest-api/pom.xml                     |  77 ++++
 .../rest/api/service/SCIMConfService.java       |  53 +++
 ext/scimv2/rest-cxf/pom.xml                     |  72 ++++
 .../rest/cxf/service/SCIMConfServiceImpl.java   |  41 ++
 .../syncope/ext/scimv2/api/data/Display.java    |  46 ---
 .../syncope/ext/scimv2/api/data/Reference.java  |  11 +-
 .../syncope/ext/scimv2/api/data/SCIMBean.java   |   2 +-
 .../ext/scimv2/api/data/SCIMComplexValue.java   |  71 ++++
 .../ext/scimv2/api/data/SCIMEnterpriseInfo.java |  96 +++++
 .../syncope/ext/scimv2/api/data/SCIMUser.java   | 165 +++++++-
 .../ext/scimv2/api/data/SCIMUserAddress.java    | 117 ++++++
 .../ext/scimv2/api/data/SCIMUserManager.java    |  63 +++
 .../ext/scimv2/api/data/SCIMUserName.java       |  96 +++++
 .../scimv2/api/data/ServiceProviderConfig.java  |  11 +
 .../syncope/ext/scimv2/api/data/Value.java      |  39 ++
 .../ext/scimv2/api/service/GroupService.java    |   2 +-
 .../ext/scimv2/api/service/RootService.java     |  59 ---
 .../ext/scimv2/api/service/SCIMService.java     |  40 +-
 .../ext/scimv2/api/service/SearchService.java   |  41 ++
 .../ext/scimv2/api/service/UserService.java     |   2 +-
 .../syncope/ext/scimv2/cxf/AddETagFilter.java   |   2 +-
 .../scimv2/cxf/service/AbstractSCIMService.java | 236 -----------
 .../ext/scimv2/cxf/service/AbstractService.java | 160 ++++++++
 .../scimv2/cxf/service/GroupServiceImpl.java    |   4 +-
 .../ext/scimv2/cxf/service/RootServiceImpl.java |  68 ----
 .../ext/scimv2/cxf/service/SCIMServiceImpl.java |  68 ++++
 .../ext/scimv2/cxf/service/UserServiceImpl.java |   4 +-
 fit/console-reference/pom.xml                   |   6 +
 .../src/test/resources/rebel.xml                |   6 +
 fit/core-reference/pom.xml                      |  25 +-
 .../main/resources/all/scimv2-logic.properties  |  21 -
 .../org/apache/syncope/fit/AbstractITCase.java  |   4 +
 .../org/apache/syncope/fit/core/SCIMITCase.java |  31 ++
 fit/core-reference/src/test/resources/rebel.xml |   6 +
 68 files changed, 3294 insertions(+), 691 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/archetype/src/main/resources/archetype-resources/console/pom.xml
----------------------------------------------------------------------
diff --git a/archetype/src/main/resources/archetype-resources/console/pom.xml b/archetype/src/main/resources/archetype-resources/console/pom.xml
index 2006755..8506fa9 100644
--- a/archetype/src/main/resources/archetype-resources/console/pom.xml
+++ b/archetype/src/main/resources/archetype-resources/console/pom.xml
@@ -141,6 +141,12 @@ under the License.
         </dependency>
         
         <dependency>
+          <groupId>org.apache.syncope.ext.scimv2</groupId>
+          <artifactId>syncope-ext-scimv2-client-console</artifactId>
+          <version>${syncope.version}</version>
+        </dependency>
+
+        <dependency>
           <groupId>org.activiti</groupId>
           <artifactId>activiti-webapp-explorer2</artifactId>            
           <type>war</type>

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/archetype/src/main/resources/archetype-resources/core/pom.xml
----------------------------------------------------------------------
diff --git a/archetype/src/main/resources/archetype-resources/core/pom.xml b/archetype/src/main/resources/archetype-resources/core/pom.xml
index f4ea761..69c36c4 100644
--- a/archetype/src/main/resources/archetype-resources/core/pom.xml
+++ b/archetype/src/main/resources/archetype-resources/core/pom.xml
@@ -193,6 +193,17 @@ under the License.
         </dependency>
 
         <dependency>
+          <groupId>org.apache.syncope.ext.scimv2</groupId>
+          <artifactId>syncope-ext-scimv2-rest-cxf</artifactId>
+          <version>${project.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.syncope.ext.scimv2</groupId>
+          <artifactId>syncope-ext-scimv2-scim-rest-cxf</artifactId>
+          <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
           <groupId>org.apache.syncope.ext</groupId>
           <artifactId>syncope-ext-swagger-ui</artifactId>
           <version>${syncope.version}</version>

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java
index ab2eec8..2826bb7 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersDirectoryPanel.java
@@ -100,7 +100,7 @@ public class ParametersDirectoryPanel
                 target.add(container);
             }
         });
-
+        modalDetails.size(Modal.Size.Medium);
         addInnerObject(modalDetails);
 
         this.addNewItemPanelBuilder(new AbstractModalPanelBuilder<AttrTO>(new AttrTO(), pageRef) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
index 2231bdf..d382c7b 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
@@ -224,7 +224,7 @@ public class RoleDirectoryPanel extends DirectoryPanel<RoleTO, RoleWrapper, Role
                             modal.show(false);
                             modal.close(target);
                         } catch (Exception e) {
-                            LOG.error("While updating onsole layout info for role {}", info.getKey(), e);
+                            LOG.error("While updating console layout info for role {}", info.getKey(), e);
                             SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
                                     ? e.getClass().getName() : e.getMessage());
                         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/client-console/pom.xml
----------------------------------------------------------------------
diff --git a/ext/scimv2/client-console/pom.xml b/ext/scimv2/client-console/pom.xml
new file mode 100644
index 0000000..278072e
--- /dev/null
+++ b/ext/scimv2/client-console/pom.xml
@@ -0,0 +1,78 @@
+<?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.ext</groupId>
+    <artifactId>syncope-ext-scimv2</artifactId>
+    <version>2.0.7-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Ext: SCIMv2 Client Console</name>
+  <description>Apache Syncope Ext: SCIMv2 Client Console</description>
+  <groupId>org.apache.syncope.ext.scimv2</groupId>
+  <artifactId>syncope-ext-scimv2-client-console</artifactId>
+  <packaging>jar</packaging>
+  
+  <properties>
+    <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>javax.servlet-api</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-common-lib</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-rest-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.client</groupId>
+      <artifactId>syncope-client-console</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+      </plugin>
+    </plugins>
+    
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+        <filtering>true</filtering>
+      </resource>
+    </resources>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/pages/SCIMConf.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/pages/SCIMConf.java b/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/pages/SCIMConf.java
new file mode 100644
index 0000000..bd22f03
--- /dev/null
+++ b/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/pages/SCIMConf.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.client.console.pages;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.annotations.ExtPage;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.rest.SCIMConfRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.console.wicket.markup.html.form.JsonEditorPanel;
+import org.apache.syncope.common.lib.scim.SCIMComplexConf;
+import org.apache.syncope.common.lib.scim.SCIMEnterpriseUserConf;
+import org.apache.syncope.common.lib.scim.SCIMUserConf;
+import org.apache.syncope.common.lib.scim.SCIMUserNameConf;
+import org.apache.syncope.common.lib.scim.types.EmailCanonicalType;
+import org.apache.syncope.common.lib.scim.types.SCIMEntitlement;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+@ExtPage(label = "SCIM 2.0", icon = "fa-cloud", listEntitlement = SCIMEntitlement.SCIM_CONF_GET, priority = 100)
+public class SCIMConf extends BaseExtPage {
+
+    private static final long serialVersionUID = 9128779230455599119L;
+
+    private static final ObjectMapper MAPPER = new ObjectMapper();
+
+    private final SCIMConfRestClient restClient = new SCIMConfRestClient();
+
+    public SCIMConf(final PageParameters parameters) {
+        super(parameters);
+
+        body.add(BookmarkablePageLinkBuilder.build("dashboard", "dashboardBr", Dashboard.class));
+
+        final BaseModal<String> modal = new BaseModal<>("modal");
+        modal.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() {
+
+            private static final long serialVersionUID = 8804221891699487139L;
+
+            @Override
+            public void onClose(final AjaxRequestTarget target) {
+                modal.show(false);
+            }
+        });
+        modal.size(Modal.Size.Large);
+        modal.addSubmitButton();
+        body.add(modal);
+
+        WebMarkupContainer content = new WebMarkupContainer("content");
+        content.setOutputMarkupId(true);
+        body.add(content);
+
+        String confString = "";
+        try {
+            org.apache.syncope.common.lib.scim.SCIMConf conf = restClient.get();
+            if (conf.getUserConf() == null) {
+                conf.setUserConf(new SCIMUserConf());
+            }
+            if (conf.getUserConf().getName() == null) {
+                conf.getUserConf().setName(new SCIMUserNameConf());
+            }
+            if (conf.getUserConf().getEmails().isEmpty()) {
+                conf.getUserConf().getEmails().add(new SCIMComplexConf<EmailCanonicalType>());
+            }
+
+            if (conf.getEnterpriseUserConf() == null) {
+                conf.setEnterpriseUserConf(new SCIMEnterpriseUserConf());
+            }
+
+            confString = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(conf);
+        } catch (Exception e) {
+            LOG.error("While reading SCIM configuration", e);
+            SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
+                    ? e.getClass().getName() : e.getMessage());
+        }
+        final Model<String> confModel = Model.of(confString);
+
+        content.add(new AjaxLink<Void>("edit") {
+
+            private static final long serialVersionUID = -4331619903296515985L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                modal.header(new ResourceModel("editConf"));
+                modal.setContent(new JsonEditorPanel(modal, confModel, false, getPageReference()) {
+
+                    private static final long serialVersionUID = -8927036362466990179L;
+
+                    @Override
+                    public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
+                        try {
+                            restClient.set(MAPPER.readValue(
+                                    confModel.getObject(), org.apache.syncope.common.lib.scim.SCIMConf.class));
+
+                            SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
+                            modal.show(false);
+                            modal.close(target);
+                        } catch (Exception e) {
+                            LOG.error("While setting SCIM configuration", e);
+                            SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
+                                    ? e.getClass().getName() : e.getMessage());
+                        }
+                        ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
+                    }
+                });
+                modal.show(true);
+                target.add(modal);
+            }
+        });
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/rest/SCIMConfRestClient.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/rest/SCIMConfRestClient.java b/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/rest/SCIMConfRestClient.java
new file mode 100644
index 0000000..95ae663
--- /dev/null
+++ b/ext/scimv2/client-console/src/main/java/org/apache/syncope/client/console/rest/SCIMConfRestClient.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.rest;
+
+import org.apache.syncope.common.lib.scim.SCIMConf;
+import org.apache.syncope.common.rest.api.service.SCIMConfService;
+
+public class SCIMConfRestClient extends BaseRestClient {
+
+    private static final long serialVersionUID = -8572714521320571470L;
+
+    public SCIMConf get() {
+        return getService(SCIMConfService.class).get();
+    }
+
+    public void set(final SCIMConf conf) {
+        getService(SCIMConfService.class).set(conf);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf.html
----------------------------------------------------------------------
diff --git a/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf.html b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf.html
new file mode 100644
index 0000000..aa1e725
--- /dev/null
+++ b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+  <wicket:extend>
+    <section class="content-header">
+      <h1>&nbsp;</h1>
+      <ol class="breadcrumb">
+        <li><a wicket:id="dashboardBr"><i class="fa fa-dashboard"></i> <wicket:message key="dashboard"/></a></li>
+        <li class="active"><wicket:message key="extensions"/></li>
+        <li class="active">SCIM 2.0</li>
+      </ol>
+    </section>
+
+    <section class="content" wicket:id="content">
+      <div class="logviewer-btn">
+        <a class="btn btn-primary" wicket:id="edit"> <wicket:message key="editConf"/>
+          <span class="fa fa-edit"></span>
+        </a>
+      </div>
+    </section>
+
+    <div wicket:id="modal"/>
+  </wicket:extend>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf.properties
----------------------------------------------------------------------
diff --git a/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf.properties b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf.properties
new file mode 100644
index 0000000..e7f31e6
--- /dev/null
+++ b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf.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.
+editConf=SCIM 2.0 configuration

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_it.properties
----------------------------------------------------------------------
diff --git a/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_it.properties b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_it.properties
new file mode 100644
index 0000000..3655a0f
--- /dev/null
+++ b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_it.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.
+editConf=Configurazione SCIM 2.0

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_pt_BR.properties
----------------------------------------------------------------------
diff --git a/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_pt_BR.properties b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_pt_BR.properties
new file mode 100644
index 0000000..e7f31e6
--- /dev/null
+++ b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_pt_BR.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.
+editConf=SCIM 2.0 configuration

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_ru.properties
----------------------------------------------------------------------
diff --git a/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_ru.properties b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_ru.properties
new file mode 100644
index 0000000..e7f31e6
--- /dev/null
+++ b/ext/scimv2/client-console/src/main/resources/org/apache/syncope/client/console/pages/SCIMConf_ru.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.
+editConf=SCIM 2.0 configuration

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/common-lib/pom.xml
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/pom.xml b/ext/scimv2/common-lib/pom.xml
new file mode 100644
index 0000000..285a798
--- /dev/null
+++ b/ext/scimv2/common-lib/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<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.ext</groupId>
+    <artifactId>syncope-ext-scimv2</artifactId>
+    <version>2.0.7-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Ext: SCIMv2 Common Lib</name>
+  <description>Apache Syncope Ext: SCIMv2 Common Lib</description>
+  <groupId>org.apache.syncope.ext.scimv2</groupId>
+  <artifactId>syncope-ext-scimv2-common-lib</artifactId>
+  <packaging>jar</packaging>
+  
+  <properties>
+    <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.syncope.common</groupId>
+      <artifactId>syncope-common-lib</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMComplexConf.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMComplexConf.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMComplexConf.java
new file mode 100644
index 0000000..84cb3fa
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMComplexConf.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.scim;
+
+import java.io.Serializable;
+
+public class SCIMComplexConf<E extends Enum<?>> implements Serializable {
+
+    private static final long serialVersionUID = -6205072829179565927L;
+
+    private String value;
+
+    private String display;
+
+    private E type;
+
+    private boolean primary;
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(final String value) {
+        this.value = value;
+    }
+
+    public String getDisplay() {
+        return display;
+    }
+
+    public void setDisplay(final String display) {
+        this.display = display;
+    }
+
+    public E getType() {
+        return type;
+    }
+
+    public void setType(final E type) {
+        this.type = type;
+    }
+
+    public boolean isPrimary() {
+        return primary;
+    }
+
+    public void setPrimary(final boolean primary) {
+        this.primary = primary;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMConf.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMConf.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMConf.java
new file mode 100644
index 0000000..e7cc2a4
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMConf.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.scim;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import java.io.Serializable;
+import java.util.Date;
+import org.apache.commons.lang3.StringUtils;
+
+public class SCIMConf implements Serializable {
+
+    private static final long serialVersionUID = 5032136914118958611L;
+
+    public static final String KEY = "scimv2.conf";
+
+    private Date creationDate = new Date();
+
+    private Date lastChangeDate = new Date();
+
+    private int bulkMaxOperations = 1000;
+
+    private int bulkMaxPayloadSize = 1048576;
+
+    private int filterMaxResults = 200;
+
+    private SCIMUserConf userConf;
+
+    private SCIMEnterpriseUserConf enterpriseUserConf;
+
+    public Date getCreationDate() {
+        if (creationDate != null) {
+            return new Date(creationDate.getTime());
+        }
+        return null;
+    }
+
+    public void setCreationDate(final Date creationDate) {
+        if (creationDate != null) {
+            this.creationDate = new Date(creationDate.getTime());
+        } else {
+            this.creationDate = null;
+        }
+    }
+
+    public Date getLastChangeDate() {
+        if (lastChangeDate != null) {
+            return new Date(lastChangeDate.getTime());
+        }
+        return null;
+    }
+
+    public void setLastChangeDate(final Date lastChangeDate) {
+        if (lastChangeDate != null) {
+            this.lastChangeDate = new Date(lastChangeDate.getTime());
+        } else {
+            this.lastChangeDate = null;
+        }
+    }
+
+    @JsonIgnore
+    public String getETagValue() {
+        Date etagDate = getLastChangeDate() == null
+                ? getCreationDate() : getLastChangeDate();
+        return etagDate == null
+                ? StringUtils.EMPTY
+                : String.valueOf(etagDate.getTime());
+
+    }
+
+    public int getBulkMaxOperations() {
+        return bulkMaxOperations;
+    }
+
+    public void setBulkMaxOperations(final int bulkMaxOperations) {
+        this.bulkMaxOperations = bulkMaxOperations;
+    }
+
+    public int getBulkMaxPayloadSize() {
+        return bulkMaxPayloadSize;
+    }
+
+    public void setBulkMaxPayloadSize(final int bulkMaxPayloadSize) {
+        this.bulkMaxPayloadSize = bulkMaxPayloadSize;
+    }
+
+    public int getFilterMaxResults() {
+        return filterMaxResults;
+    }
+
+    public void setFilterMaxResults(final int filterMaxResults) {
+        this.filterMaxResults = filterMaxResults;
+    }
+
+    public SCIMUserConf getUserConf() {
+        return userConf;
+    }
+
+    public void setUserConf(final SCIMUserConf userConf) {
+        this.userConf = userConf;
+    }
+
+    public SCIMEnterpriseUserConf getEnterpriseUserConf() {
+        return enterpriseUserConf;
+    }
+
+    public void setEnterpriseUserConf(final SCIMEnterpriseUserConf enterpriseUserConf) {
+        this.enterpriseUserConf = enterpriseUserConf;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMEnterpriseUserConf.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMEnterpriseUserConf.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMEnterpriseUserConf.java
new file mode 100644
index 0000000..4cf7b88
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMEnterpriseUserConf.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.scim;
+
+import java.io.Serializable;
+
+public class SCIMEnterpriseUserConf implements Serializable {
+
+    private static final long serialVersionUID = 5929414914887282638L;
+
+    private String employeeNumber;
+
+    private String costCenter;
+
+    private String organization;
+
+    private String division;
+
+    private String department;
+
+    private SCIMManagerConf manager;
+
+    public String getEmployeeNumber() {
+        return employeeNumber;
+    }
+
+    public void setEmployeeNumber(final String employeeNumber) {
+        this.employeeNumber = employeeNumber;
+    }
+
+    public String getCostCenter() {
+        return costCenter;
+    }
+
+    public void setCostCenter(final String costCenter) {
+        this.costCenter = costCenter;
+    }
+
+    public String getOrganization() {
+        return organization;
+    }
+
+    public void setOrganization(final String organization) {
+        this.organization = organization;
+    }
+
+    public String getDivision() {
+        return division;
+    }
+
+    public void setDivision(final String division) {
+        this.division = division;
+    }
+
+    public String getDepartment() {
+        return department;
+    }
+
+    public void setDepartment(final String department) {
+        this.department = department;
+    }
+
+    public SCIMManagerConf getManager() {
+        return manager;
+    }
+
+    public void setManager(final SCIMManagerConf manager) {
+        this.manager = manager;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMManagerConf.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMManagerConf.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMManagerConf.java
new file mode 100644
index 0000000..481eb5f
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMManagerConf.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.scim;
+
+import java.io.Serializable;
+
+public class SCIMManagerConf implements Serializable {
+
+    private static final long serialVersionUID = -1443695570207406613L;
+
+    private String manager;
+
+    private String displayName;
+
+    public String getManager() {
+        return manager;
+    }
+
+    public void setManager(final String manager) {
+        this.manager = manager;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public void setDisplayName(final String displayName) {
+        this.displayName = displayName;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserAddressConf.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserAddressConf.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserAddressConf.java
new file mode 100644
index 0000000..ed5643a
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserAddressConf.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.scim;
+
+import java.io.Serializable;
+import org.apache.syncope.common.lib.scim.types.AddressCanonicalType;
+
+public class SCIMUserAddressConf implements Serializable {
+
+    private static final long serialVersionUID = 8093531407836615577L;
+
+    private String formatted;
+
+    private String streetAddress;
+
+    private String locality;
+
+    private String region;
+
+    private String postalCode;
+
+    private String country;
+
+    private AddressCanonicalType type;
+
+    private boolean primary;
+
+    public String getFormatted() {
+        return formatted;
+    }
+
+    public void setFormatted(final String formatted) {
+        this.formatted = formatted;
+    }
+
+    public String getStreetAddress() {
+        return streetAddress;
+    }
+
+    public void setStreetAddress(final String streetAddress) {
+        this.streetAddress = streetAddress;
+    }
+
+    public String getLocality() {
+        return locality;
+    }
+
+    public void setLocality(final String locality) {
+        this.locality = locality;
+    }
+
+    public String getRegion() {
+        return region;
+    }
+
+    public void setRegion(final String region) {
+        this.region = region;
+    }
+
+    public String getPostalCode() {
+        return postalCode;
+    }
+
+    public void setPostalCode(final String postalCode) {
+        this.postalCode = postalCode;
+    }
+
+    public String getCountry() {
+        return country;
+    }
+
+    public void setCountry(final String country) {
+        this.country = country;
+    }
+
+    public AddressCanonicalType getType() {
+        return type;
+    }
+
+    public void setType(final AddressCanonicalType type) {
+        this.type = type;
+    }
+
+    public boolean isPrimary() {
+        return primary;
+    }
+
+    public void setPrimary(final boolean primary) {
+        this.primary = primary;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserConf.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserConf.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserConf.java
new file mode 100644
index 0000000..7d1be73
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserConf.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.scim;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.syncope.common.lib.scim.types.EmailCanonicalType;
+import org.apache.syncope.common.lib.scim.types.IMCanonicalType;
+import org.apache.syncope.common.lib.scim.types.PhoneNumberCanonicalType;
+import org.apache.syncope.common.lib.scim.types.PhotoCanonicalType;
+
+public class SCIMUserConf implements Serializable {
+
+    private static final long serialVersionUID = -2700011089067219156L;
+
+    private SCIMUserNameConf name;
+
+    private String displayName;
+
+    private String nickName;
+
+    private String profileUrl;
+
+    private String title;
+
+    private String userType;
+
+    private String preferredLanguage;
+
+    private String locale;
+
+    private String timezone;
+
+    private final List<SCIMComplexConf<EmailCanonicalType>> emails = new ArrayList<>();
+
+    private final List<SCIMComplexConf<PhoneNumberCanonicalType>> phoneNumbers = new ArrayList<>();
+
+    private final List<SCIMComplexConf<IMCanonicalType>> ims = new ArrayList<>();
+
+    private final List<SCIMComplexConf<PhotoCanonicalType>> photos = new ArrayList<>();
+
+    private final List<SCIMUserAddressConf> addresses = new ArrayList<>();
+
+    private final List<String> x509Certificates = new ArrayList<>();
+
+    public SCIMUserNameConf getName() {
+        return name;
+    }
+
+    public void setName(final SCIMUserNameConf name) {
+        this.name = name;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public void setDisplayName(final String displayName) {
+        this.displayName = displayName;
+    }
+
+    public String getNickName() {
+        return nickName;
+    }
+
+    public void setNickName(final String nickName) {
+        this.nickName = nickName;
+    }
+
+    public String getProfileUrl() {
+        return profileUrl;
+    }
+
+    public void setProfileUrl(final String profileUrl) {
+        this.profileUrl = profileUrl;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(final String title) {
+        this.title = title;
+    }
+
+    public String getUserType() {
+        return userType;
+    }
+
+    public void setUserType(final String userType) {
+        this.userType = userType;
+    }
+
+    public String getPreferredLanguage() {
+        return preferredLanguage;
+    }
+
+    public void setPreferredLanguage(final String preferredLanguage) {
+        this.preferredLanguage = preferredLanguage;
+    }
+
+    public String getLocale() {
+        return locale;
+    }
+
+    public void setLocale(final String locale) {
+        this.locale = locale;
+    }
+
+    public String getTimezone() {
+        return timezone;
+    }
+
+    public void setTimezone(final String timezone) {
+        this.timezone = timezone;
+    }
+
+    public List<SCIMComplexConf<EmailCanonicalType>> getEmails() {
+        return emails;
+    }
+
+    public List<SCIMComplexConf<PhoneNumberCanonicalType>> getPhoneNumbers() {
+        return phoneNumbers;
+    }
+
+    public List<SCIMComplexConf<IMCanonicalType>> getIms() {
+        return ims;
+    }
+
+    public List<SCIMComplexConf<PhotoCanonicalType>> getPhotos() {
+        return photos;
+    }
+
+    public List<SCIMUserAddressConf> getAddresses() {
+        return addresses;
+    }
+
+    public List<String> getX509Certificates() {
+        return x509Certificates;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserNameConf.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserNameConf.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserNameConf.java
new file mode 100644
index 0000000..2f2db0f
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/SCIMUserNameConf.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.scim;
+
+import java.io.Serializable;
+
+public class SCIMUserNameConf implements Serializable {
+
+    private static final long serialVersionUID = -2256008193008290376L;
+
+    private String formatted;
+
+    private String familyName;
+
+    private String givenName;
+
+    private String middleName;
+
+    private String honorificPrefix;
+
+    private String honorificSuffix;
+
+    public String getFormatted() {
+        return formatted;
+    }
+
+    public void setFormatted(final String formatted) {
+        this.formatted = formatted;
+    }
+
+    public String getFamilyName() {
+        return familyName;
+    }
+
+    public void setFamilyName(final String familyName) {
+        this.familyName = familyName;
+    }
+
+    public String getGivenName() {
+        return givenName;
+    }
+
+    public void setGivenName(final String givenName) {
+        this.givenName = givenName;
+    }
+
+    public String getMiddleName() {
+        return middleName;
+    }
+
+    public void setMiddleName(final String middleName) {
+        this.middleName = middleName;
+    }
+
+    public String getHonorificPrefix() {
+        return honorificPrefix;
+    }
+
+    public void setHonorificPrefix(final String honorificPrefix) {
+        this.honorificPrefix = honorificPrefix;
+    }
+
+    public String getHonorificSuffix() {
+        return honorificSuffix;
+    }
+
+    public void setHonorificSuffix(final String honorificSuffix) {
+        this.honorificSuffix = honorificSuffix;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/AddressCanonicalType.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/AddressCanonicalType.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/AddressCanonicalType.java
new file mode 100644
index 0000000..cf2cb13
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/AddressCanonicalType.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.common.lib.scim.types;
+
+public enum AddressCanonicalType {
+    work,
+    home,
+    other
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/EmailCanonicalType.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/EmailCanonicalType.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/EmailCanonicalType.java
new file mode 100644
index 0000000..986c9f6
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/EmailCanonicalType.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.common.lib.scim.types;
+
+public enum EmailCanonicalType {
+    work,
+    home,
+    other
+
+}

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

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/PhoneNumberCanonicalType.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/PhoneNumberCanonicalType.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/PhoneNumberCanonicalType.java
new file mode 100644
index 0000000..72ff342
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/PhoneNumberCanonicalType.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.common.lib.scim.types;
+
+public enum PhoneNumberCanonicalType {
+    work,
+    home,
+    mobile,
+    fax,
+    pager,
+    other
+
+}

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

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/SCIMEntitlement.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/SCIMEntitlement.java b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/SCIMEntitlement.java
new file mode 100644
index 0000000..8a8a1ae
--- /dev/null
+++ b/ext/scimv2/common-lib/src/main/java/org/apache/syncope/common/lib/scim/types/SCIMEntitlement.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.scim.types;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Collections;
+import java.util.Set;
+import java.util.TreeSet;
+
+public final class SCIMEntitlement {
+
+    public static final String SCIM_CONF_GET = "SCIM_CONF_GET";
+
+    public static final String SCIM_CONF_SET = "SCIM_CONF_SET";
+
+    private static final Set<String> VALUES;
+
+    static {
+        Set<String> values = new TreeSet<>();
+        for (Field field : SCIMEntitlement.class.getDeclaredFields()) {
+            if (Modifier.isStatic(field.getModifiers()) && String.class.equals(field.getType())) {
+                values.add(field.getName());
+            }
+        }
+        VALUES = Collections.unmodifiableSet(values);
+    }
+
+    public static Set<String> values() {
+        return VALUES;
+    }
+
+    private SCIMEntitlement() {
+        // private constructor for static utility class
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/logic/pom.xml
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/pom.xml b/ext/scimv2/logic/pom.xml
index 188d71e..c186912 100644
--- a/ext/scimv2/logic/pom.xml
+++ b/ext/scimv2/logic/pom.xml
@@ -52,6 +52,12 @@ under the License.
     </dependency>
     
     <dependency>
+      <groupId>org.apache.syncope.ext.scimv2</groupId>
+      <artifactId>syncope-ext-scimv2-common-lib</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    
+    <dependency>
       <groupId>org.antlr</groupId>
       <artifactId>antlr4-runtime</artifactId>
     </dependency>

http://git-wip-us.apache.org/repos/asf/syncope/blob/1aa7bcaf/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/RootLogic.java
----------------------------------------------------------------------
diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/RootLogic.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/RootLogic.java
deleted file mode 100644
index 75d0ecf..0000000
--- a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/RootLogic.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.logic;
-
-import java.lang.reflect.Method;
-import java.net.URI;
-import java.util.Arrays;
-import java.util.List;
-import javax.ws.rs.NotFoundException;
-import javax.ws.rs.core.UriBuilder;
-import org.apache.syncope.common.lib.AbstractBaseBean;
-import org.apache.syncope.core.logic.init.SCIMLoader;
-import org.apache.syncope.ext.scimv2.api.data.AuthenticationScheme;
-import org.apache.syncope.ext.scimv2.api.data.BulkConfigurationOption;
-import org.apache.syncope.ext.scimv2.api.data.ConfigurationOption;
-import org.apache.syncope.ext.scimv2.api.data.FilterConfigurationOption;
-import org.apache.syncope.ext.scimv2.api.data.Meta;
-import org.apache.syncope.ext.scimv2.api.data.ResourceType;
-import org.apache.syncope.ext.scimv2.api.data.SchemaExtension;
-import org.apache.syncope.ext.scimv2.api.data.ServiceProviderConfig;
-import org.apache.syncope.ext.scimv2.api.type.Resource;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.stereotype.Component;
-
-@Component
-public class RootLogic extends AbstractLogic<AbstractBaseBean> {
-
-    private static final Object MONITOR = new Object();
-
-    private static ServiceProviderConfig SERVICE_PROVIDER_CONFIG;
-
-    private static ResourceType USER;
-
-    private static ResourceType GROUP;
-
-    @Autowired
-    private SCIMLoader loader;
-
-    @PreAuthorize("isAuthenticated()")
-    public ServiceProviderConfig serviceProviderConfig() {
-        synchronized (MONITOR) {
-            if (SERVICE_PROVIDER_CONFIG == null) {
-                SERVICE_PROVIDER_CONFIG = new ServiceProviderConfig(
-                        new ConfigurationOption(true),
-                        new BulkConfigurationOption(
-                                true, loader.getBulkMaxOperations(), loader.getBulkMaxPayloadSize()),
-                        new FilterConfigurationOption(true, loader.getFilterMaxResults()),
-                        new ConfigurationOption(true),
-                        new ConfigurationOption(true),
-                        new ConfigurationOption(true));
-                SERVICE_PROVIDER_CONFIG.getAuthenticationSchemes().add(new AuthenticationScheme(
-                        "JSON Web Token",
-                        "Apache Syncope JWT authentication",
-                        URI.create("http://www.rfc-editor.org/info/rfc6750"),
-                        URI.create("https://syncope.apache.org/docs/"
-                                + "reference-guide.html#rest-authentication-and-authorization"),
-                        "oauthbearertoken",
-                        true));
-                SERVICE_PROVIDER_CONFIG.getAuthenticationSchemes().add(new AuthenticationScheme(
-                        "HTTP Basic",
-                        "Apache Syncope HTTP Basic authentication",
-                        URI.create("http://www.rfc-editor.org/info/rfc2617"),
-                        URI.create("https://syncope.apache.org/docs/"
-                                + "reference-guide.html#rest-authentication-and-authorization"),
-                        "httpbasic",
-                        false));
-            }
-        }
-        return SERVICE_PROVIDER_CONFIG;
-    }
-
-    @PreAuthorize("isAuthenticated()")
-    public List<ResourceType> resourceTypes(final UriBuilder uriBuilder) {
-        synchronized (MONITOR) {
-            if (USER == null) {
-                USER = new ResourceType("User", "User", "/Users", "User Account", Resource.User.schema(),
-                        new Meta(Resource.ResourceType,
-                                null, null, null, uriBuilder.path("User").build().toASCIIString()));
-                USER.getSchemaExtensions().add(new SchemaExtension(Resource.EnterpriseUser.schema(), true));
-            }
-            if (GROUP == null) {
-                GROUP = new ResourceType("Group", "Group", "/Groups", "Group", Resource.Group.schema(),
-                        new Meta(Resource.ResourceType,
-                                null, null, null, uriBuilder.path("Group").build().toASCIIString()));
-            }
-        }
-
-        return Arrays.asList(USER, GROUP);
-    }
-
-    @PreAuthorize("isAuthenticated()")
-    public ResourceType resourceType(final UriBuilder uriBuilder, final String type) {
-        if (Resource.User.name().equals(type)) {
-            resourceTypes(uriBuilder);
-            return USER;
-        } else if (Resource.Group.name().equals(type)) {
-            resourceTypes(uriBuilder);
-            return GROUP;
-        } else {
-            throw new IllegalArgumentException("Unsupported resource type: " + type);
-        }
-    }
-
-    @PreAuthorize("isAuthenticated()")
-    public String schemas() {
-        return loader.getSchemas();
-    }
-
-    @PreAuthorize("isAuthenticated()")
-    public String schema(final String schema) {
-        String found = loader.getSchema(schema);
-        if (found == null) {
-            throw new NotFoundException("Schema " + schema);
-        }
-
-        return found;
-    }
-
-    @Override
-    protected AbstractBaseBean resolveReference(final Method method, final Object... args)
-            throws UnresolvedReferenceException {
-
-        throw new UnresolvedReferenceException();
-    }
-
-}