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

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

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">