You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2015/02/12 10:14:20 UTC

[15/54] [abbrv] [partial] syncope git commit: [SYNCOPE-620] Renaming 'server' after 'core', to provide continuity with older releases (especially for archetype)

http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/RestServiceExceptionMapper.java
----------------------------------------------------------------------
diff --git a/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/RestServiceExceptionMapper.java b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/RestServiceExceptionMapper.java
new file mode 100644
index 0000000..dbfb327
--- /dev/null
+++ b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/RestServiceExceptionMapper.java
@@ -0,0 +1,285 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.persistence.EntityExistsException;
+import javax.persistence.PersistenceException;
+import javax.persistence.RollbackException;
+import javax.validation.ValidationException;
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+import org.apache.cxf.jaxrs.client.ResponseExceptionMapper;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
+import org.apache.cxf.jaxrs.validation.ValidationExceptionMapper;
+import org.apache.syncope.common.lib.SyncopeClientCompositeException;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ErrorTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.core.misc.security.UnauthorizedRoleException;
+import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
+import org.apache.syncope.core.persistence.api.dao.DuplicateException;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.workflow.api.WorkflowException;
+import org.identityconnectors.framework.common.exceptions.ConfigurationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.orm.jpa.JpaSystemException;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.transaction.TransactionSystemException;
+
+@Provider
+public class RestServiceExceptionMapper implements ExceptionMapper<Exception>, ResponseExceptionMapper<Exception> {
+
+    private static final String BASIC_REALM_UNAUTHORIZED = "Basic realm=\"Apache Syncope authentication\"";
+
+    private static final Logger LOG = LoggerFactory.getLogger(RestServiceExceptionMapper.class);
+
+    private final ValidationExceptionMapper validationEM = new ValidationExceptionMapper();
+
+    @Override
+    public Response toResponse(final Exception ex) {
+        LOG.error("Exception thrown by REST method: " + ex.getMessage(), ex);
+
+        ResponseBuilder builder;
+
+        if (ex instanceof SyncopeClientException) {
+            SyncopeClientException sce = (SyncopeClientException) ex;
+            builder = sce.isComposite()
+                    ? getSyncopeClientCompositeExceptionResponse(sce.asComposite())
+                    : getSyncopeClientExceptionResponse(sce);
+        } else if (ex instanceof WebApplicationException) {
+            Response response = ((WebApplicationException) ex).getResponse();
+
+            ErrorTO error = new ErrorTO();
+            error.setStatus(response.getStatus());
+            error.setType(ClientExceptionType.Unknown);
+            error.getElements().add(getExMessage(ex));
+
+            builder = JAXRSUtils.fromResponse(response).entity(error);
+        } else if (ex instanceof AccessDeniedException) {
+            builder = Response.status(Response.Status.UNAUTHORIZED).
+                    header(HttpHeaders.WWW_AUTHENTICATE, BASIC_REALM_UNAUTHORIZED);
+        } else if (ex instanceof UnauthorizedRoleException) {
+            builder = builder(Response.Status.UNAUTHORIZED, ClientExceptionType.UnauthorizedRole, getExMessage(ex));
+        } else if (ex instanceof EntityExistsException || ex instanceof DuplicateException) {
+            builder = builder(Response.Status.CONFLICT, ClientExceptionType.EntityExists, getExMessage(ex));
+        } else if (ex instanceof DataIntegrityViolationException) {
+            builder = builder(Response.Status.CONFLICT, ClientExceptionType.DataIntegrityViolation, getExMessage(ex));
+        } else {
+            builder = processNotFoundExceptions(ex);
+            if (builder == null) {
+                builder = processInvalidEntityExceptions(ex);
+                if (builder == null) {
+                    builder = processBadRequestExceptions(ex);
+                }
+                // process JAX-RS validation errors
+                if (builder == null && ex instanceof ValidationException) {
+                    builder = JAXRSUtils.fromResponse(validationEM.toResponse((ValidationException) ex)).
+                            header(RESTHeaders.ERROR_CODE, ClientExceptionType.RESTValidation.getHeaderValue()).
+                            header(RESTHeaders.ERROR_INFO,
+                                    ClientExceptionType.RESTValidation.getInfoHeaderValue(getExMessage(ex)));
+
+                    ErrorTO error = new ErrorTO();
+                    error.setStatus(ClientExceptionType.RESTValidation.getResponseStatus().getStatusCode());
+                    error.setType(ClientExceptionType.RESTValidation);
+                    error.getElements().add(getExMessage(ex));
+                    builder.entity(error);
+                }
+                // ...or just report as InternalServerError
+                if (builder == null) {
+                    builder = Response.status(Response.Status.INTERNAL_SERVER_ERROR).
+                            header(RESTHeaders.ERROR_INFO,
+                                    ClientExceptionType.Unknown.getInfoHeaderValue(getExMessage(ex)));
+
+                    ErrorTO error = new ErrorTO();
+                    error.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
+                    error.setType(ClientExceptionType.Unknown);
+                    error.getElements().add(getExMessage(ex));
+                    builder.entity(error);
+                }
+            }
+        }
+
+        return builder.build();
+    }
+
+    @Override
+    public Exception fromResponse(final Response r) {
+        throw new UnsupportedOperationException(
+                "Call of fromResponse() method is not expected in RestServiceExceptionMapper");
+    }
+
+    private ResponseBuilder getSyncopeClientExceptionResponse(final SyncopeClientException ex) {
+        ResponseBuilder builder = Response.status(ex.getType().getResponseStatus());
+        builder.header(RESTHeaders.ERROR_CODE, ex.getType().getHeaderValue());
+
+        ErrorTO error = new ErrorTO();
+        error.setStatus(ex.getType().getResponseStatus().getStatusCode());
+        error.setType(ex.getType());
+
+        for (String element : ex.getElements()) {
+            builder.header(RESTHeaders.ERROR_INFO, ex.getType().getInfoHeaderValue(element));
+            error.getElements().add(element);
+        }
+
+        return builder.entity(error);
+    }
+
+    private ResponseBuilder getSyncopeClientCompositeExceptionResponse(final SyncopeClientCompositeException ex) {
+        if (ex.getExceptions().size() == 1) {
+            return getSyncopeClientExceptionResponse(ex.getExceptions().iterator().next());
+        }
+
+        ResponseBuilder builder = Response.status(Response.Status.BAD_REQUEST);
+
+        List<ErrorTO> errors = new ArrayList<ErrorTO>();
+        for (SyncopeClientException sce : ex.getExceptions()) {
+            builder.header(RESTHeaders.ERROR_CODE, sce.getType().getHeaderValue());
+
+            ErrorTO error = new ErrorTO();
+            error.setStatus(sce.getType().getResponseStatus().getStatusCode());
+            error.setType(sce.getType());
+
+            for (String element : sce.getElements()) {
+                builder.header(RESTHeaders.ERROR_INFO, ex.getType().getInfoHeaderValue(element));
+                error.getElements().add(element);
+            }
+
+            errors.add(error);
+        }
+
+        return builder.entity(errors);
+    }
+
+    private ResponseBuilder processNotFoundExceptions(final Exception ex) {
+        if (ex instanceof javax.ws.rs.NotFoundException || ex instanceof NotFoundException) {
+            return builder(Response.Status.NOT_FOUND, ClientExceptionType.NotFound, getExMessage(ex));
+        }
+
+        return null;
+    }
+
+    private ResponseBuilder processInvalidEntityExceptions(final Exception ex) {
+        InvalidEntityException iee = null;
+
+        if (ex instanceof InvalidEntityException) {
+            iee = (InvalidEntityException) ex;
+        }
+        if (ex instanceof TransactionSystemException && ex.getCause() instanceof RollbackException
+                && ex.getCause().getCause() instanceof InvalidEntityException) {
+
+            iee = (InvalidEntityException) ex.getCause().getCause();
+        }
+
+        if (iee != null) {
+            ClientExceptionType exType =
+                    iee.getEntityClassSimpleName().endsWith("Policy")
+                            ? ClientExceptionType.InvalidPolicy
+                            : ClientExceptionType.valueOf("Invalid" + iee.getEntityClassSimpleName());
+
+            ResponseBuilder builder = Response.status(Response.Status.BAD_REQUEST);
+            builder.header(RESTHeaders.ERROR_CODE, exType.getHeaderValue());
+
+            ErrorTO error = new ErrorTO();
+            error.setStatus(exType.getResponseStatus().getStatusCode());
+            error.setType(exType);
+
+            for (Map.Entry<Class<?>, Set<EntityViolationType>> violation : iee.getViolations().entrySet()) {
+                for (EntityViolationType violationType : violation.getValue()) {
+                    builder.header(RESTHeaders.ERROR_INFO,
+                            exType.getInfoHeaderValue(violationType.name() + ": " + violationType.getMessage()));
+                    error.getElements().add(violationType.name() + ": " + violationType.getMessage());
+                }
+            }
+
+            return builder;
+        }
+
+        return null;
+    }
+
+    private ResponseBuilder processBadRequestExceptions(final Exception ex) {
+        ResponseBuilder builder = Response.status(Response.Status.BAD_REQUEST);
+
+        // This exception might be raised by Activiti (if enabled)
+        Class<?> ibatisPersistenceException = null;
+        try {
+            ibatisPersistenceException = Class.forName("org.apache.ibatis.exceptions.PersistenceException");
+        } catch (ClassNotFoundException e) {
+            // ignore
+        }
+
+        if (ex instanceof BadRequestException) {
+            if (((BadRequestException) ex).getResponse() == null) {
+                return builder;
+            } else {
+                return JAXRSUtils.fromResponse(((BadRequestException) ex).getResponse());
+            }
+        } else if (ex instanceof WorkflowException) {
+            return builder(Response.Status.BAD_REQUEST, ClientExceptionType.Workflow, getExMessage(ex));
+        } else if (ex instanceof PersistenceException) {
+            return builder(Response.Status.BAD_REQUEST, ClientExceptionType.GenericPersistence, getExMessage(ex));
+        } else if (ibatisPersistenceException != null && ibatisPersistenceException.isAssignableFrom(ex.getClass())) {
+            return builder(Response.Status.BAD_REQUEST, ClientExceptionType.Workflow,
+                    getMessage(ex, "Currently unavailable. Please try later."));
+        } else if (ex instanceof JpaSystemException) {
+            return builder(Response.Status.BAD_REQUEST, ClientExceptionType.DataIntegrityViolation, getExMessage(ex));
+        } else if (ex instanceof ConfigurationException) {
+            return builder(Response.Status.BAD_REQUEST, ClientExceptionType.InvalidConnIdConf, getExMessage(ex));
+        } else if (ex instanceof ParsingValidationException) {
+            return builder(Response.Status.BAD_REQUEST, ClientExceptionType.InvalidValues, getExMessage(ex));
+        }
+
+        return null;
+    }
+
+    private ResponseBuilder builder(final Response.Status status, final ClientExceptionType hType, final String msg) {
+        ResponseBuilder builder = Response.status(status).
+                header(RESTHeaders.ERROR_CODE, hType.getHeaderValue()).
+                header(RESTHeaders.ERROR_INFO, hType.getInfoHeaderValue(msg));
+
+        ErrorTO error = new ErrorTO();
+        error.setStatus(status.getStatusCode());
+        error.setType(hType);
+        error.getElements().add(msg);
+
+        return builder.entity(error);
+    }
+
+    private String getMessage(final Throwable ex, final String msg) {
+        return (msg == null) ? getExMessage(ex) : msg;
+    }
+
+    private String getExMessage(final Throwable ex) {
+        return (ex.getCause() == null) ? ex.getMessage() : ex.getCause().getMessage();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/ThreadLocalCleanupListener.java
----------------------------------------------------------------------
diff --git a/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/ThreadLocalCleanupListener.java b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/ThreadLocalCleanupListener.java
new file mode 100644
index 0000000..39f5573
--- /dev/null
+++ b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/ThreadLocalCleanupListener.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.rest.cxf;
+
+import javax.servlet.ServletRequestEvent;
+import javax.servlet.ServletRequestListener;
+import org.apache.syncope.core.misc.DataFormat;
+import org.identityconnectors.common.l10n.CurrentLocale;
+import org.identityconnectors.framework.impl.api.local.ThreadClassLoaderManager;
+
+/**
+ * Remove any known thread-local variable when the servlet request is destroyed.
+ */
+public class ThreadLocalCleanupListener implements ServletRequestListener {
+
+    @Override
+    public void requestInitialized(final ServletRequestEvent sre) {
+        // nothing to do while setting up this request (and thread)
+    }
+
+    @Override
+    public void requestDestroyed(final ServletRequestEvent sre) {
+        DataFormat.clear();
+
+        ThreadClassLoaderManager.clearInstance();
+        CurrentLocale.clear();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/WADLServlet.java
----------------------------------------------------------------------
diff --git a/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/WADLServlet.java b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/WADLServlet.java
new file mode 100644
index 0000000..e5d5c74
--- /dev/null
+++ b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/WADLServlet.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.core.rest.cxf;
+
+import java.io.IOException;
+import java.net.URL;
+import java.rmi.ServerException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.cocoon.pipeline.CachingPipeline;
+import org.apache.cocoon.pipeline.Pipeline;
+import org.apache.cocoon.sax.SAXPipelineComponent;
+import org.apache.cocoon.sax.component.XMLGenerator;
+import org.apache.cocoon.sax.component.XMLSerializer;
+import org.apache.cocoon.sax.component.XSLTTransformer;
+
+public class WADLServlet extends HttpServlet {
+
+    private static final long serialVersionUID = -6737005675471095560L;
+
+    private static final Pattern SCHEMA_PATTERN = Pattern.compile("/schema_(.*)_(.*)\\.html");
+
+    /**
+     * Handles the HTTP <code>GET</code> method.
+     *
+     * @param request servlet request
+     * @param response servlet response
+     * @throws ServletException if a servlet-specific error occurs
+     * @throws IOException if an I/O error occurs
+     */
+    @Override
+    protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
+            throws ServletException, IOException {
+
+        String requestURI = request.getRequestURI().substring(
+                request.getRequestURI().indexOf(request.getServletPath()) + request.getServletPath().length());
+        Matcher schemaMatcher = SCHEMA_PATTERN.matcher(requestURI);
+
+        Pipeline<SAXPipelineComponent> pipeline = new CachingPipeline<SAXPipelineComponent>();
+        final String wadlURL = request.getRequestURL().
+                substring(0, request.getRequestURL().indexOf("/doc")) + "/?_wadl";
+        pipeline.addComponent(new XMLGenerator(new URL(wadlURL)));
+        if ("/".equals(requestURI)) {
+            XSLTTransformer xslt = new XSLTTransformer(getClass().getResource("/wadl2html/index.xsl"));
+
+            Map<String, Object> parameters = new HashMap<>();
+            parameters.put("contextPath", request.getContextPath());
+            xslt.setParameters(parameters);
+
+            pipeline.addComponent(xslt);
+        } else if (schemaMatcher.matches()) {
+            XSLTTransformer xslt = new XSLTTransformer(getClass().getResource("/wadl2html/schema.xsl"));
+
+            Map<String, Object> parameters = new HashMap<>();
+            parameters.put("contextPath", request.getContextPath());
+            parameters.put("schema-position", schemaMatcher.group(1));
+            parameters.put("schema-prefix", schemaMatcher.group(2));
+            xslt.setParameters(parameters);
+
+            pipeline.addComponent(xslt);
+        } else {
+            throw new ServerException("URL not supported: " + request.getRequestURI());
+        }
+
+        pipeline.addComponent(XMLSerializer.createHTML4Serializer());
+        pipeline.setup(response.getOutputStream());
+        try {
+            pipeline.execute();
+        } catch (Exception e) {
+            throw new ServletException(e);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractServiceImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractServiceImpl.java b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractServiceImpl.java
new file mode 100644
index 0000000..f6fb69a
--- /dev/null
+++ b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractServiceImpl.java
@@ -0,0 +1,227 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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 java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.cxf.jaxrs.ext.MessageContext;
+import org.apache.cxf.jaxrs.ext.search.SearchBean;
+import org.apache.cxf.jaxrs.ext.search.SearchCondition;
+import org.apache.cxf.jaxrs.ext.search.SearchContext;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.PagedResult;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.rest.api.service.JAXRSService;
+import org.apache.syncope.common.rest.api.Preference;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.core.misc.search.SearchCondVisitor;
+import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+abstract class AbstractServiceImpl implements JAXRSService {
+
+    /**
+     * Logger.
+     */
+    protected static final Logger LOG = LoggerFactory.getLogger(AbstractServiceImpl.class);
+
+    protected static final String OPTIONS_ALLOW = "GET,POST,OPTIONS,HEAD";
+
+    @Context
+    protected UriInfo uriInfo;
+
+    @Context
+    protected MessageContext messageContext;
+
+    @Context
+    protected SearchContext searchContext;
+
+    /**
+     * Reads <tt>Prefer</tt> header from request and parses into a <tt>Preference</tt> instance.
+     *
+     * @return a <tt>Preference</tt> instance matching the passed <tt>Prefer</tt> header,
+     * or <tt>Preference.NONE</tt> if missing.
+     */
+    protected Preference getPreference() {
+        return Preference.fromString(messageContext.getHttpHeaders().getHeaderString(RESTHeaders.PREFER));
+    }
+
+    /**
+     * Builds response to successful <tt>create</tt> request, taking into account any <tt>Prefer</tt> header.
+     *
+     * @param id identifier of the created entity
+     * @param entity the entity just created
+     * @return response to successful <tt>create</tt> request
+     */
+    protected Response createResponse(final Object id, final Object entity) {
+        URI location = uriInfo.getAbsolutePathBuilder().path(String.valueOf(id)).build();
+
+        Response.ResponseBuilder builder = Response.
+                created(location).
+                header(RESTHeaders.RESOURCE_ID, id);
+
+        switch (getPreference()) {
+            case RETURN_NO_CONTENT:
+                break;
+
+            case RETURN_CONTENT:
+            case NONE:
+            default:
+                builder = builder.entity(entity);
+                break;
+
+        }
+        if (getPreference() == Preference.RETURN_CONTENT || getPreference() == Preference.RETURN_NO_CONTENT) {
+            builder = builder.header(RESTHeaders.PREFERENCE_APPLIED, getPreference().toString());
+        }
+
+        return builder.build();
+    }
+
+    /**
+     * Builds response to successful modification request, taking into account any <tt>Prefer</tt> header.
+     *
+     * @param entity the entity just modified
+     * @return response to successful modification request
+     */
+    protected Response modificationResponse(final Object entity) {
+        Response.ResponseBuilder builder;
+        switch (getPreference()) {
+            case RETURN_NO_CONTENT:
+                builder = Response.noContent();
+                break;
+
+            case RETURN_CONTENT:
+            case NONE:
+            default:
+                builder = Response.ok(entity);
+                break;
+        }
+        if (getPreference() == Preference.RETURN_CONTENT || getPreference() == Preference.RETURN_NO_CONTENT) {
+            builder = builder.header(RESTHeaders.PREFERENCE_APPLIED, getPreference().toString());
+        }
+
+        return builder.build();
+    }
+
+    protected void checkETag(final String etag) {
+        Response.ResponseBuilder builder = messageContext.getRequest().evaluatePreconditions(new EntityTag(etag));
+        if (builder != null) {
+            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.ConcurrentModification);
+            sce.getElements().add("Mismatching ETag value");
+            throw sce;
+        }
+    }
+
+    protected SearchCond getSearchCond(final String fiql) {
+        try {
+            SearchCondVisitor visitor = new SearchCondVisitor();
+            SearchCondition<SearchBean> sc = searchContext.getCondition(fiql, SearchBean.class);
+            sc.accept(visitor);
+
+            return visitor.getQuery();
+        } catch (Exception e) {
+            LOG.error("Invalid FIQL expression: {}", fiql, e);
+
+            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidSearchExpression);
+            sce.getElements().add(fiql);
+            throw sce;
+        }
+    }
+
+    protected List<OrderByClause> getOrderByClauses(final String orderBy) {
+        if (StringUtils.isBlank(orderBy)) {
+            return Collections.<OrderByClause>emptyList();
+        }
+
+        List<OrderByClause> result = new ArrayList<>();
+
+        for (String clause : orderBy.split(",")) {
+            String[] elems = clause.split(" ");
+
+            if (elems.length > 0 && StringUtils.isNotBlank(elems[0])) {
+                OrderByClause obc = new OrderByClause();
+                obc.setField(elems[0].trim());
+                if (elems.length > 1 && StringUtils.isNotBlank(elems[1])) {
+                    obc.setDirection(elems[1].trim().equalsIgnoreCase(OrderByClause.Direction.ASC.name())
+                            ? OrderByClause.Direction.ASC : OrderByClause.Direction.DESC);
+                }
+                result.add(obc);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Builds a paged result out of a list of items and additional information.
+     *
+     * @param <T> result type
+     * @param list bare list of items to be returned
+     * @param page current page
+     * @param size requested size
+     * @param totalCount total result size (not considering pagination)
+     * @return paged result
+     */
+    protected <T extends AbstractBaseBean> PagedResult<T> buildPagedResult(
+            final List<T> list, final int page, final int size, final int totalCount) {
+
+        PagedResult<T> result = new PagedResult<>();
+        result.getResult().addAll(list);
+
+        result.setPage(page);
+        result.setSize(result.getResult().size());
+        result.setTotalCount(totalCount);
+
+        UriBuilder builder = uriInfo.getAbsolutePathBuilder();
+        MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
+        for (Map.Entry<String, List<String>> queryParam : queryParams.entrySet()) {
+            builder = builder.queryParam(queryParam.getKey(), queryParam.getValue().toArray());
+        }
+
+        if (result.getPage() > 1) {
+            result.setPrev(builder.
+                    replaceQueryParam(PARAM_PAGE, result.getPage() - 1).
+                    replaceQueryParam(PARAM_SIZE, size).
+                    build());
+        }
+        if ((result.getPage() - 1) * size + result.getSize() < totalCount) {
+            result.setNext(builder.
+                    replaceQueryParam(PARAM_PAGE, result.getPage() + 1).
+                    replaceQueryParam(PARAM_SIZE, size).
+                    build());
+        }
+
+        return result;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AddETagFilter.java
----------------------------------------------------------------------
diff --git a/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AddETagFilter.java b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AddETagFilter.java
new file mode 100644
index 0000000..bdb40ac
--- /dev/null
+++ b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AddETagFilter.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.rest.cxf.service;
+
+import java.io.IOException;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.ext.Provider;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.to.AbstractAnnotatedBean;
+
+/**
+ * Adds the <tt>ETag</tt> filter to any response containing an instance of <tt>AbstractSysInfoTO</tt> as entity.
+ * The actual ETag value is computed on the basis of last change date (or creation date if not available).
+ *
+ * @see AbstractSysInfoTO
+ */
+@Provider
+public class AddETagFilter implements ContainerResponseFilter {
+
+    @Override
+    public void filter(final ContainerRequestContext reqCtx, final ContainerResponseContext resCtx) throws IOException {
+        if (resCtx.getEntity() instanceof AbstractAnnotatedBean && resCtx.getEntityTag() == null) {
+            AbstractAnnotatedBean sysInfo = (AbstractAnnotatedBean) resCtx.getEntity();
+            String etagValue = sysInfo.getETagValue();
+            if (StringUtils.isNotBlank(etagValue)) {
+                resCtx.getHeaders().add(HttpHeaders.ETAG, new EntityTag(etagValue).toString());
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ConfigurationServiceImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ConfigurationServiceImpl.java b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ConfigurationServiceImpl.java
new file mode 100644
index 0000000..90bb6be
--- /dev/null
+++ b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ConfigurationServiceImpl.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.rest.cxf.service;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.StreamingOutput;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.ConfTO;
+import org.apache.syncope.common.rest.api.service.ConfigurationService;
+import org.apache.syncope.core.logic.ConfigurationLogic;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ConfigurationServiceImpl extends AbstractServiceImpl implements ConfigurationService {
+
+    private static final String CONTENT_XML = "content.xml";
+
+    @Autowired
+    private ConfigurationLogic logic;
+
+    @Override
+    public Response export() {
+        StreamingOutput sout = new StreamingOutput() {
+
+            @Override
+            public void write(final OutputStream os) throws IOException {
+                logic.export(os);
+            }
+        };
+        return Response.ok(sout).
+                type(MediaType.TEXT_XML).
+                header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + CONTENT_XML).
+                build();
+    }
+
+    @Override
+    public void delete(final String key) {
+        logic.delete(key);
+    }
+
+    @Override
+    public ConfTO list() {
+        return logic.list();
+    }
+
+    @Override
+    public AttrTO read(final String key) {
+        return logic.read(key);
+    }
+
+    @Override
+    public void set(final String key, final AttrTO value) {
+        value.setSchema(key);
+        logic.set(value);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ConnectorServiceImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ConnectorServiceImpl.java b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ConnectorServiceImpl.java
new file mode 100644
index 0000000..1ba5674
--- /dev/null
+++ b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ConnectorServiceImpl.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.rest.cxf.service;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.to.BulkAction;
+import org.apache.syncope.common.lib.to.BulkActionResult;
+import org.apache.syncope.common.lib.to.ConnBundleTO;
+import org.apache.syncope.common.lib.to.ConnIdObjectClassTO;
+import org.apache.syncope.common.lib.to.ConnInstanceTO;
+import org.apache.syncope.common.lib.to.PlainSchemaTO;
+import org.apache.syncope.common.lib.types.ConnConfProperty;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.ConnectorService;
+import org.apache.syncope.core.logic.ConnectorLogic;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ConnectorServiceImpl extends AbstractServiceImpl implements ConnectorService {
+
+    @Autowired
+    private ConnectorLogic logic;
+
+    @Override
+    public Response create(final ConnInstanceTO connInstanceTO) {
+        ConnInstanceTO connInstance = logic.create(connInstanceTO);
+        URI location = uriInfo.getAbsolutePathBuilder().path(String.valueOf(connInstance.getKey())).build();
+        return Response.created(location).
+                header(RESTHeaders.RESOURCE_ID, connInstance.getKey()).
+                build();
+    }
+
+    @Override
+    public void delete(final Long connInstanceKey) {
+        logic.delete(connInstanceKey);
+    }
+
+    @Override
+    public List<ConnBundleTO> getBundles(final String lang) {
+        return logic.getBundles(lang);
+    }
+
+    @Override
+    public List<ConnConfProperty> getConfigurationProperties(final Long connInstanceKey) {
+        return logic.getConfigurationProperties(connInstanceKey);
+    }
+
+    @Override
+    public List<PlainSchemaTO> getSchemaNames(final Long connInstanceKey, final ConnInstanceTO connInstanceTO,
+            final boolean includeSpecial) {
+
+        connInstanceTO.setKey(connInstanceKey);
+
+        List<String> schemaNames = logic.getSchemaNames(connInstanceTO, includeSpecial);
+        List<PlainSchemaTO> result = new ArrayList<>(schemaNames.size());
+        for (String name : schemaNames) {
+            PlainSchemaTO schemaTO = new PlainSchemaTO();
+            schemaTO.setKey(name);
+            result.add(schemaTO);
+        }
+        return result;
+    }
+
+    @Override
+    public List<ConnIdObjectClassTO> getSupportedObjectClasses(final Long connInstanceKey,
+            final ConnInstanceTO connInstanceTO) {
+
+        connInstanceTO.setKey(connInstanceKey);
+
+        List<String> objectClasses = logic.getSupportedObjectClasses(connInstanceTO);
+        List<ConnIdObjectClassTO> result = new ArrayList<>(objectClasses.size());
+        for (String objectClass : objectClasses) {
+            result.add(new ConnIdObjectClassTO(objectClass));
+        }
+        return result;
+    }
+
+    @Override
+    public List<ConnInstanceTO> list(final String lang) {
+        return logic.list(lang);
+    }
+
+    @Override
+    public ConnInstanceTO read(final Long connInstanceKey) {
+        return logic.read(connInstanceKey);
+    }
+
+    @Override
+    public ConnInstanceTO readByResource(final String resourceName) {
+        return logic.readByResource(resourceName);
+    }
+
+    @Override
+    public void update(final Long connInstanceKey, final ConnInstanceTO connInstanceTO) {
+        connInstanceTO.setKey(connInstanceKey);
+        logic.update(connInstanceTO);
+    }
+
+    @Override
+    public boolean check(final ConnInstanceTO connInstanceTO) {
+        return logic.check(connInstanceTO);
+    }
+
+    @Override
+    public void reload() {
+        logic.reload();
+    }
+
+    @Override
+    public BulkActionResult bulk(final BulkAction bulkAction) {
+        return logic.bulk(bulkAction);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/EntitlementServiceImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/EntitlementServiceImpl.java b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/EntitlementServiceImpl.java
new file mode 100644
index 0000000..8d2b2a4
--- /dev/null
+++ b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/EntitlementServiceImpl.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.rest.cxf.service;
+
+import java.util.List;
+import org.apache.syncope.common.lib.wrap.EntitlementTO;
+import org.apache.syncope.common.rest.api.CollectionWrapper;
+import org.apache.syncope.common.rest.api.service.EntitlementService;
+import org.apache.syncope.core.logic.EntitlementLogic;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class EntitlementServiceImpl extends AbstractServiceImpl implements EntitlementService {
+
+    @Autowired
+    private EntitlementLogic logic;
+
+    @Override
+    public List<EntitlementTO> getAllEntitlements() {
+        return CollectionWrapper.wrap(logic.getAll(), EntitlementTO.class);
+    }
+
+    @Override
+    public List<EntitlementTO> getOwnEntitlements() {
+        return CollectionWrapper.wrap(logic.getOwn(), EntitlementTO.class);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/LoggerServiceImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/LoggerServiceImpl.java b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/LoggerServiceImpl.java
new file mode 100644
index 0000000..2ae9136
--- /dev/null
+++ b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/LoggerServiceImpl.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.rest.cxf.service;
+
+import java.text.ParseException;
+import java.util.List;
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.NotFoundException;
+import org.apache.syncope.common.lib.to.EventCategoryTO;
+import org.apache.syncope.common.lib.to.LoggerTO;
+import org.apache.syncope.common.lib.types.AuditLoggerName;
+import org.apache.syncope.common.lib.types.LoggerType;
+import org.apache.syncope.common.rest.api.CollectionWrapper;
+import org.apache.syncope.common.rest.api.service.LoggerService;
+import org.apache.syncope.core.logic.LoggerLogic;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class LoggerServiceImpl extends AbstractServiceImpl implements LoggerService {
+
+    @Autowired
+    private LoggerLogic logic;
+
+    @Override
+    public void delete(final LoggerType type, final String name) {
+        switch (type) {
+            case LOG:
+                logic.deleteLog(name);
+                break;
+
+            case AUDIT:
+                try {
+                    logic.disableAudit(AuditLoggerName.fromLoggerName(name));
+                } catch (IllegalArgumentException e) {
+                    throw new BadRequestException(e);
+                } catch (ParseException e) {
+                    throw new BadRequestException(e);
+                }
+                break;
+
+            default:
+                throw new BadRequestException();
+        }
+
+    }
+
+    @Override
+    public List<LoggerTO> list(final LoggerType type) {
+        switch (type) {
+            case LOG:
+                return logic.listLogs();
+
+            case AUDIT:
+                List<AuditLoggerName> auditLogger = logic.listAudits();
+                return CollectionWrapper.unwrapLogger(auditLogger);
+
+            default:
+                throw new BadRequestException();
+        }
+    }
+
+    @Override
+    public LoggerTO read(final LoggerType type, final String name) {
+        List<LoggerTO> logger = list(type);
+        for (LoggerTO l : logger) {
+            if (l.getKey().equals(name)) {
+                return l;
+            }
+        }
+        throw new NotFoundException();
+    }
+
+    @Override
+    public void update(final LoggerType type, final String name, final LoggerTO logger) {
+        switch (type) {
+            case LOG:
+                logic.setLogLevel(name, logger.getLevel().getLevel());
+                break;
+
+            case AUDIT:
+                try {
+                    logic.enableAudit(AuditLoggerName.fromLoggerName(name));
+                } catch (Exception e) {
+                    throw new BadRequestException(e);
+                }
+                break;
+
+            default:
+                throw new BadRequestException();
+        }
+    }
+
+    @Override
+    public List<EventCategoryTO> events() {
+        return logic.listAuditEvents();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/NotificationServiceImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/NotificationServiceImpl.java b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/NotificationServiceImpl.java
new file mode 100644
index 0000000..4691189
--- /dev/null
+++ b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/NotificationServiceImpl.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.rest.cxf.service;
+
+import java.net.URI;
+import java.util.List;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.to.NotificationTO;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.NotificationService;
+import org.apache.syncope.core.logic.NotificationLogic;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class NotificationServiceImpl extends AbstractServiceImpl implements NotificationService {
+
+    @Autowired
+    private NotificationLogic logic;
+
+    @Override
+    public Response create(final NotificationTO notificationTO) {
+        NotificationTO created = logic.create(notificationTO);
+        URI location = uriInfo.getAbsolutePathBuilder().path(String.valueOf(created.getKey())).build();
+        return Response.created(location).
+                header(RESTHeaders.RESOURCE_ID, created.getKey()).
+                build();
+    }
+
+    @Override
+    public NotificationTO read(final Long notificationKey) {
+        return logic.read(notificationKey);
+    }
+
+    @Override
+    public List<NotificationTO> list() {
+        return logic.list();
+    }
+
+    @Override
+    public void update(final Long notificationKey, final NotificationTO notificationTO) {
+        notificationTO.setKey(notificationKey);
+        logic.update(notificationTO);
+    }
+
+    @Override
+    public void delete(final Long notificationKey) {
+        logic.delete(notificationKey);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PolicyServiceImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PolicyServiceImpl.java b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PolicyServiceImpl.java
new file mode 100644
index 0000000..ac4df8a
--- /dev/null
+++ b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PolicyServiceImpl.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.rest.cxf.service;
+
+import java.net.URI;
+import java.util.List;
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.to.AbstractPolicyTO;
+import org.apache.syncope.common.lib.to.AccountPolicyTO;
+import org.apache.syncope.common.lib.to.PasswordPolicyTO;
+import org.apache.syncope.common.lib.to.SyncPolicyTO;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.PolicyService;
+import org.apache.syncope.core.logic.PolicyLogic;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class PolicyServiceImpl extends AbstractServiceImpl implements PolicyService {
+
+    @Autowired
+    private PolicyLogic logic;
+
+    @Override
+    public <T extends AbstractPolicyTO> Response create(final T policyTO) {
+        AbstractPolicyTO policy = logic.create(policyTO);
+        URI location = uriInfo.getAbsolutePathBuilder().path(String.valueOf(policy.getKey())).build();
+        return Response.created(location).
+                header(RESTHeaders.RESOURCE_ID, policy.getKey()).
+                build();
+    }
+
+    @Override
+    public void delete(final Long policyKey) {
+        logic.delete(policyKey);
+    }
+
+    @Override
+    public <T extends AbstractPolicyTO> List<T> list(final PolicyType type) {
+        return logic.list(type);
+    }
+
+    @Override
+    public <T extends AbstractPolicyTO> T read(final Long policyKey) {
+        return logic.read(policyKey);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends AbstractPolicyTO> T readGlobal(final PolicyType type) {
+        T result = null;
+
+        switch (type) {
+            case ACCOUNT:
+            case GLOBAL_ACCOUNT:
+                result = (T) logic.getGlobalAccountPolicy();
+                break;
+
+            case PASSWORD:
+            case GLOBAL_PASSWORD:
+                result = (T) logic.getGlobalPasswordPolicy();
+                break;
+
+            case SYNC:
+            case GLOBAL_SYNC:
+                result = (T) logic.getGlobalSyncPolicy();
+                break;
+
+            default:
+                throw new BadRequestException();
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T extends AbstractPolicyTO> void update(final Long policyKey, final T policyTO) {
+        policyTO.setKey(policyKey);
+
+        switch (policyTO.getType()) {
+            case ACCOUNT:
+            case GLOBAL_ACCOUNT:
+                logic.update((AccountPolicyTO) policyTO);
+                break;
+
+            case PASSWORD:
+            case GLOBAL_PASSWORD:
+                logic.update((PasswordPolicyTO) policyTO);
+                break;
+
+            case SYNC:
+            case GLOBAL_SYNC:
+                logic.update((SyncPolicyTO) policyTO);
+                break;
+
+            default:
+                break;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReportServiceImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReportServiceImpl.java b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReportServiceImpl.java
new file mode 100644
index 0000000..3fd69a4
--- /dev/null
+++ b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReportServiceImpl.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.rest.cxf.service;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URI;
+import java.util.List;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.StreamingOutput;
+import org.apache.syncope.common.lib.to.PagedResult;
+import org.apache.syncope.common.lib.to.ReportExecTO;
+import org.apache.syncope.common.lib.to.ReportTO;
+import org.apache.syncope.common.lib.types.ReportExecExportFormat;
+import org.apache.syncope.common.lib.wrap.ReportletConfClass;
+import org.apache.syncope.common.rest.api.CollectionWrapper;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.ReportService;
+import org.apache.syncope.core.logic.ReportLogic;
+import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.core.persistence.api.entity.ReportExec;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ReportServiceImpl extends AbstractServiceImpl implements ReportService {
+
+    @Autowired
+    private ReportLogic logic;
+
+    @Override
+    public Response create(final ReportTO reportTO) {
+        ReportTO createdReportTO = logic.create(reportTO);
+        URI location = uriInfo.getAbsolutePathBuilder().path(String.valueOf(createdReportTO.getKey())).build();
+        return Response.created(location).
+                header(RESTHeaders.RESOURCE_ID.toString(), createdReportTO.getKey()).
+                build();
+    }
+
+    @Override
+    public void update(final Long reportKey, final ReportTO reportTO) {
+        reportTO.setKey(reportKey);
+        logic.update(reportTO);
+    }
+
+    @Override
+    public PagedResult<ReportTO> list() {
+        return list(DEFAULT_PARAM_PAGE_VALUE, DEFAULT_PARAM_SIZE_VALUE, null);
+    }
+
+    @Override
+    public PagedResult<ReportTO> list(final String orderBy) {
+        return list(DEFAULT_PARAM_PAGE_VALUE, DEFAULT_PARAM_SIZE_VALUE, orderBy);
+    }
+
+    @Override
+    public PagedResult<ReportTO> list(final Integer page, final Integer size) {
+        return list(page, size, null);
+    }
+
+    @Override
+    public PagedResult<ReportTO> list(final Integer page, final Integer size, final String orderBy) {
+        List<OrderByClause> orderByClauses = getOrderByClauses(orderBy);
+        return buildPagedResult(logic.list(page, size, orderByClauses), page, size, logic.count());
+    }
+
+    @Override
+    public List<ReportletConfClass> getReportletConfClasses() {
+        return CollectionWrapper.wrap(logic.getReportletConfClasses(), ReportletConfClass.class);
+    }
+
+    @Override
+    public ReportTO read(final Long reportKey) {
+        return logic.read(reportKey);
+    }
+
+    @Override
+    public ReportExecTO readExecution(final Long executionKey) {
+        return logic.readExecution(executionKey);
+    }
+
+    @Override
+    public Response exportExecutionResult(final Long executionKey, final ReportExecExportFormat fmt) {
+        final ReportExecExportFormat format = (fmt == null) ? ReportExecExportFormat.XML : fmt;
+        final ReportExec reportExec = logic.getAndCheckReportExec(executionKey);
+        StreamingOutput sout = new StreamingOutput() {
+
+            @Override
+            public void write(final OutputStream os) throws IOException {
+                logic.exportExecutionResult(os, reportExec, format);
+            }
+        };
+        String disposition = "attachment; filename=" + reportExec.getReport().getName() + "." + format.name().
+                toLowerCase();
+        return Response.ok(sout).
+                header(HttpHeaders.CONTENT_DISPOSITION, disposition).
+                build();
+    }
+
+    @Override
+    public ReportExecTO execute(final Long reportKey) {
+        return logic.execute(reportKey);
+    }
+
+    @Override
+    public void delete(final Long reportKey) {
+        logic.delete(reportKey);
+    }
+
+    @Override
+    public void deleteExecution(final Long executionKey) {
+        logic.deleteExecution(executionKey);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ResourceServiceImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ResourceServiceImpl.java b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ResourceServiceImpl.java
new file mode 100644
index 0000000..1feee38
--- /dev/null
+++ b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ResourceServiceImpl.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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 java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+import org.apache.syncope.common.lib.to.BulkAction;
+import org.apache.syncope.common.lib.to.BulkActionResult;
+import org.apache.syncope.common.lib.to.ConnObjectTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.types.ResourceDeassociationActionType;
+import org.apache.syncope.common.lib.types.SubjectType;
+import org.apache.syncope.common.lib.wrap.SubjectKey;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.ResourceService;
+import org.apache.syncope.core.logic.AbstractResourceAssociator;
+import org.apache.syncope.core.logic.ResourceLogic;
+import org.apache.syncope.core.logic.RoleLogic;
+import org.apache.syncope.core.logic.UserLogic;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ResourceServiceImpl extends AbstractServiceImpl implements ResourceService {
+
+    @Autowired
+    private ResourceLogic logic;
+
+    @Autowired
+    private UserLogic userLogic;
+
+    @Autowired
+    private RoleLogic roleLogic;
+
+    @Override
+    public Response create(final ResourceTO resourceTO) {
+        ResourceTO created = logic.create(resourceTO);
+        URI location = uriInfo.getAbsolutePathBuilder().path(created.getKey()).build();
+        return Response.created(location).
+                header(RESTHeaders.RESOURCE_ID, created.getKey()).
+                build();
+    }
+
+    @Override
+    public void update(final String resourceKey, final ResourceTO resourceTO) {
+        resourceTO.setKey(resourceKey);
+        logic.update(resourceTO);
+    }
+
+    @Override
+    public void delete(final String resourceKey) {
+        logic.delete(resourceKey);
+    }
+
+    @Override
+    public ResourceTO read(final String resourceKey) {
+        return logic.read(resourceKey);
+    }
+
+    @Override
+    public List<ResourceTO> list() {
+        return logic.list();
+    }
+
+    @Override
+    public ConnObjectTO getConnectorObject(final String resourceKey, final SubjectType type, final Long key) {
+        return logic.getConnectorObject(resourceKey, type, key);
+    }
+
+    @Override
+    public boolean check(final ResourceTO resourceTO) {
+        return logic.check(resourceTO);
+    }
+
+    @Override
+    public BulkActionResult bulk(final BulkAction bulkAction) {
+        return logic.bulk(bulkAction);
+    }
+
+    @Override
+    public BulkActionResult bulkDeassociation(final String resourceKey, final SubjectType subjectType,
+            final ResourceDeassociationActionType type, final List<SubjectKey> subjectKeys) {
+
+        AbstractResourceAssociator<? extends AbstractAttributableTO> associator = subjectType == SubjectType.USER
+                ? userLogic
+                : roleLogic;
+
+        final BulkActionResult res = new BulkActionResult();
+
+        for (SubjectKey key : subjectKeys) {
+            final Set<String> resources = Collections.singleton(resourceKey);
+            try {
+                switch (type) {
+                    case DEPROVISION:
+                        associator.deprovision(key.getElement(), resources);
+                        break;
+
+                    case UNASSIGN:
+                        associator.unassign(key.getElement(), resources);
+                        break;
+
+                    case UNLINK:
+                        associator.unlink(key.getElement(), resources);
+                        break;
+
+                    default:
+                }
+
+                res.add(key, BulkActionResult.Status.SUCCESS);
+            } catch (Exception e) {
+                LOG.warn("While executing {} on {} {}", type, subjectType, key.getElement(), e);
+                res.add(key, BulkActionResult.Status.FAILURE);
+            }
+        }
+
+        return res;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/RoleServiceImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/RoleServiceImpl.java b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/RoleServiceImpl.java
new file mode 100644
index 0000000..b42fc2f
--- /dev/null
+++ b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/RoleServiceImpl.java
@@ -0,0 +1,227 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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 java.util.List;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.mod.RoleMod;
+import org.apache.syncope.common.lib.to.BulkAction;
+import org.apache.syncope.common.lib.to.BulkActionResult;
+import org.apache.syncope.common.lib.to.PagedResult;
+import org.apache.syncope.common.lib.to.PropagationStatus;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.types.ResourceAssociationActionType;
+import org.apache.syncope.common.lib.types.ResourceDeassociationActionType;
+import org.apache.syncope.common.lib.wrap.ResourceName;
+import org.apache.syncope.common.rest.api.CollectionWrapper;
+import org.apache.syncope.common.rest.api.service.RoleService;
+import org.apache.syncope.core.logic.RoleLogic;
+import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class RoleServiceImpl extends AbstractServiceImpl implements RoleService {
+
+    @Autowired
+    private RoleLogic logic;
+
+    @Override
+    public List<RoleTO> children(final Long roleKey) {
+        return logic.children(roleKey);
+    }
+
+    @Override
+    public Response create(final RoleTO roleTO) {
+        RoleTO created = logic.create(roleTO);
+        return createResponse(created.getKey(), created);
+    }
+
+    @Override
+    public Response delete(final Long roleKey) {
+        RoleTO role = logic.read(roleKey);
+
+        checkETag(role.getETagValue());
+
+        RoleTO deleted = logic.delete(roleKey);
+        return modificationResponse(deleted);
+    }
+
+    @Override
+    public PagedResult<RoleTO> list() {
+        return list(DEFAULT_PARAM_PAGE_VALUE, DEFAULT_PARAM_SIZE_VALUE, null);
+    }
+
+    @Override
+    public PagedResult<RoleTO> list(final String orderBy) {
+        return list(DEFAULT_PARAM_PAGE_VALUE, DEFAULT_PARAM_SIZE_VALUE, orderBy);
+    }
+
+    @Override
+    public PagedResult<RoleTO> list(final Integer page, final Integer size) {
+        return list(page, size, null);
+    }
+
+    @Override
+    public PagedResult<RoleTO> list(final Integer page, final Integer size, final String orderBy) {
+        List<OrderByClause> orderByClauses = getOrderByClauses(orderBy);
+        return buildPagedResult(logic.list(page, size, orderByClauses), page, size, logic.count());
+    }
+
+    @Override
+    public RoleTO parent(final Long roleKey) {
+        return logic.parent(roleKey);
+    }
+
+    @Override
+    public RoleTO read(final Long roleKey) {
+        return logic.read(roleKey);
+    }
+
+    @Override
+    public PagedResult<RoleTO> search(final String fiql) {
+        return search(fiql, DEFAULT_PARAM_PAGE_VALUE, DEFAULT_PARAM_SIZE_VALUE, null);
+    }
+
+    @Override
+    public PagedResult<RoleTO> search(final String fiql, final String orderBy) {
+        return search(fiql, DEFAULT_PARAM_PAGE_VALUE, DEFAULT_PARAM_SIZE_VALUE, orderBy);
+    }
+
+    @Override
+    public PagedResult<RoleTO> search(final String fiql, final Integer page, final Integer size) {
+        return search(fiql, page, size, null);
+    }
+
+    @Override
+    public PagedResult<RoleTO> search(final String fiql, final Integer page, final Integer size, final String orderBy) {
+        SearchCond cond = getSearchCond(fiql);
+        List<OrderByClause> orderByClauses = getOrderByClauses(orderBy);
+        return buildPagedResult(
+                logic.search(cond, page, size, orderByClauses), page, size, logic.searchCount(cond));
+    }
+
+    @Override
+    public RoleTO readSelf(final Long roleKey) {
+        return logic.readSelf(roleKey);
+    }
+
+    @Override
+    public Response update(final Long roleKey, final RoleMod roleMod) {
+        RoleTO role = logic.read(roleKey);
+
+        checkETag(role.getETagValue());
+
+        roleMod.setKey(roleKey);
+        RoleTO updated = logic.update(roleMod);
+        return modificationResponse(updated);
+    }
+
+    @Override
+    public Response bulkDeassociation(
+            final Long roleKey, final ResourceDeassociationActionType type, final List<ResourceName> resourceNames) {
+
+        RoleTO role = logic.read(roleKey);
+
+        checkETag(role.getETagValue());
+
+        RoleTO updated;
+        switch (type) {
+            case UNLINK:
+                updated = logic.unlink(roleKey, CollectionWrapper.unwrap(resourceNames));
+                break;
+
+            case UNASSIGN:
+                updated = logic.unassign(roleKey, CollectionWrapper.unwrap(resourceNames));
+                break;
+
+            case DEPROVISION:
+                updated = logic.deprovision(roleKey, CollectionWrapper.unwrap(resourceNames));
+                break;
+
+            default:
+                updated = logic.read(roleKey);
+        }
+
+        final BulkActionResult res = new BulkActionResult();
+
+        if (type == ResourceDeassociationActionType.UNLINK) {
+            for (ResourceName resourceName : resourceNames) {
+                res.add(resourceName.getElement(), updated.getResources().contains(resourceName.getElement())
+                        ? BulkActionResult.Status.FAILURE
+                        : BulkActionResult.Status.SUCCESS);
+            }
+        } else {
+            for (PropagationStatus propagationStatusTO : updated.getPropagationStatusTOs()) {
+                res.add(propagationStatusTO.getResource(), propagationStatusTO.getStatus().toString());
+            }
+        }
+
+        return modificationResponse(res);
+    }
+
+    @Override
+    public Response bulkAssociation(
+            final Long roleKey, final ResourceAssociationActionType type, final List<ResourceName> resourceNames) {
+
+        RoleTO role = logic.read(roleKey);
+
+        checkETag(role.getETagValue());
+
+        RoleTO updated;
+        switch (type) {
+            case LINK:
+                updated = logic.link(roleKey, CollectionWrapper.unwrap(resourceNames));
+                break;
+
+            case ASSIGN:
+                updated = logic.assign(roleKey, CollectionWrapper.unwrap(resourceNames), false, null);
+                break;
+
+            case PROVISION:
+                updated = logic.provision(roleKey, CollectionWrapper.unwrap(resourceNames), false, null);
+                break;
+
+            default:
+                updated = logic.read(roleKey);
+        }
+
+        final BulkActionResult res = new BulkActionResult();
+
+        if (type == ResourceAssociationActionType.LINK) {
+            for (ResourceName resourceName : resourceNames) {
+                res.add(resourceName.getElement(), updated.getResources().contains(resourceName.getElement())
+                        ? BulkActionResult.Status.FAILURE
+                        : BulkActionResult.Status.SUCCESS);
+            }
+        } else {
+            for (PropagationStatus propagationStatusTO : updated.getPropagationStatusTOs()) {
+                res.add(propagationStatusTO.getResource(), propagationStatusTO.getStatus().toString());
+            }
+        }
+
+        return modificationResponse(res);
+    }
+
+    @Override
+    public BulkActionResult bulk(final BulkAction bulkAction) {
+        return logic.bulk(bulkAction);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SchemaServiceImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SchemaServiceImpl.java b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SchemaServiceImpl.java
new file mode 100644
index 0000000..3082c94
--- /dev/null
+++ b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SchemaServiceImpl.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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 java.net.URI;
+import java.util.List;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.to.AbstractSchemaTO;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.SchemaService;
+import org.apache.syncope.core.logic.SchemaLogic;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class SchemaServiceImpl extends AbstractServiceImpl implements SchemaService {
+
+    @Autowired
+    private SchemaLogic logic;
+
+    @Override
+    public <T extends AbstractSchemaTO> Response create(final AttributableType attrType, final SchemaType schemaType,
+            final T schemaTO) {
+
+        T created = logic.create(attrType, schemaType, schemaTO);
+
+        URI location = uriInfo.getAbsolutePathBuilder().path(created.getKey()).build();
+        return Response.created(location).
+                header(RESTHeaders.RESOURCE_ID, created.getKey()).
+                build();
+    }
+
+    @Override
+    public void delete(final AttributableType attrType, final SchemaType schemaType, final String schemaKey) {
+        logic.delete(attrType, schemaType, schemaKey);
+    }
+
+    @Override
+    public <T extends AbstractSchemaTO> List<T> list(final AttributableType attrType, final SchemaType schemaType) {
+        return logic.list(attrType, schemaType);
+    }
+
+    @Override
+    public <T extends AbstractSchemaTO> T read(final AttributableType attrType, final SchemaType schemaType,
+            final String schemaKey) {
+
+        return logic.read(attrType, schemaType, schemaKey);
+    }
+
+    @Override
+    public <T extends AbstractSchemaTO> void update(final AttributableType attrType, final SchemaType schemaType,
+            final String schemaKey, final T schemaTO) {
+
+        schemaTO.setKey(schemaKey);
+        logic.update(attrType, schemaType, schemaTO);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SecurityQuestionServiceImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SecurityQuestionServiceImpl.java b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SecurityQuestionServiceImpl.java
new file mode 100644
index 0000000..70666b6
--- /dev/null
+++ b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SecurityQuestionServiceImpl.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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 java.net.URI;
+import java.util.List;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.to.SecurityQuestionTO;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.SecurityQuestionService;
+import org.apache.syncope.core.logic.SecurityQuestionLogic;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class SecurityQuestionServiceImpl extends AbstractServiceImpl implements SecurityQuestionService {
+
+    @Autowired
+    private SecurityQuestionLogic logic;
+
+    @Override
+    public List<SecurityQuestionTO> list() {
+        return logic.list();
+    }
+
+    @Override
+    public SecurityQuestionTO read(final Long securityQuestionId) {
+        return logic.read(securityQuestionId);
+    }
+
+    @Override
+    public Response create(final SecurityQuestionTO securityQuestionTO) {
+        SecurityQuestionTO created = logic.create(securityQuestionTO);
+
+        URI location = uriInfo.getAbsolutePathBuilder().path(String.valueOf(created.getKey())).build();
+        return Response.created(location).
+                header(RESTHeaders.RESOURCE_ID, String.valueOf(created.getKey())).
+                build();
+    }
+
+    @Override
+    public void update(final Long securityQuestionId, final SecurityQuestionTO securityQuestionTO) {
+        securityQuestionTO.setKey(securityQuestionId);
+        logic.update(securityQuestionTO);
+    }
+
+    @Override
+    public void delete(final Long securityQuestionId) {
+        logic.delete(securityQuestionId);
+    }
+
+    @Override
+    public SecurityQuestionTO readByUser(final String username) {
+        return logic.read(username);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SyncopeServiceImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SyncopeServiceImpl.java b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SyncopeServiceImpl.java
new file mode 100644
index 0000000..8227584
--- /dev/null
+++ b/syncope620/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SyncopeServiceImpl.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.rest.cxf.service;
+
+import org.apache.syncope.common.lib.to.SyncopeTO;
+import org.apache.syncope.common.rest.api.service.SyncopeService;
+import org.apache.syncope.core.logic.SyncopeLogic;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class SyncopeServiceImpl extends AbstractServiceImpl implements SyncopeService {
+
+    @Autowired
+    private SyncopeLogic logic;
+
+    @Override
+    public SyncopeTO info() {
+        return logic.info();
+    }
+
+}