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/16 09:06:43 UTC

[18/59] [abbrv] [partial] syncope git commit: [SYNCOPE-620] Re-organization completed

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/lib/pom.xml
----------------------------------------------------------------------
diff --git a/client/lib/pom.xml b/client/lib/pom.xml
new file mode 100644
index 0000000..c4886be
--- /dev/null
+++ b/client/lib/pom.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.syncope</groupId>
+    <artifactId>syncope-client</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Client Lib</name>
+  <description>Apache Syncope Client Lib</description>
+  <groupId>org.apache.syncope.client</groupId>
+  <artifactId>syncope-client-lib</artifactId>
+  <packaging>jar</packaging>
+  
+  <properties>
+    <rootpom.basedir>${basedir}/../..</rootpom.basedir>
+  </properties>
+  
+  <dependencies>
+    <dependency>
+      <groupId>javax.ws.rs</groupId>
+      <artifactId>javax.ws.rs-api</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.cxf</groupId>
+      <artifactId>cxf-rt-rs-client</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.fasterxml.jackson.jaxrs</groupId>
+      <artifactId>jackson-jaxrs-json-provider</artifactId>
+    </dependency>  
+
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.common</groupId>
+      <artifactId>syncope-common-rest-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+  
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-pmd-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/lib/src/main/java/org/apache/syncope/client/lib/RestClientExceptionMapper.java
----------------------------------------------------------------------
diff --git a/client/lib/src/main/java/org/apache/syncope/client/lib/RestClientExceptionMapper.java b/client/lib/src/main/java/org/apache/syncope/client/lib/RestClientExceptionMapper.java
new file mode 100644
index 0000000..bb772bc
--- /dev/null
+++ b/client/lib/src/main/java/org/apache/syncope/client/lib/RestClientExceptionMapper.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.lib;
+
+import java.security.AccessControlException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.ws.rs.BadRequestException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+import javax.xml.ws.WebServiceException;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.cxf.jaxrs.client.ResponseExceptionMapper;
+import org.apache.syncope.common.lib.SyncopeClientCompositeException;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Provider
+public class RestClientExceptionMapper implements ExceptionMapper<Exception>, ResponseExceptionMapper<Exception> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(RestClientExceptionMapper.class);
+
+    @Override
+    public Response toResponse(final Exception exception) {
+        throw new UnsupportedOperationException(
+                "Call of toResponse() method is not expected in RestClientExceptionnMapper");
+    }
+
+    @Override
+    public Exception fromResponse(final Response response) {
+        final int statusCode = response.getStatus();
+        Exception ex;
+
+        // 1. Check for client (possibly composite) exception in HTTP header
+        SyncopeClientCompositeException scce = checkSyncopeClientCompositeException(response);
+        if (scce != null) {
+            if (scce.getExceptions().size() == 1) {
+                ex = scce.getExceptions().iterator().next();
+            } else {
+                ex = scce;
+            }
+        } // 2. Map SC_UNAUTHORIZED
+        else if (statusCode == Response.Status.UNAUTHORIZED.getStatusCode()) {
+            ex = new AccessControlException("Remote unauthorized exception");
+        } // 3. Map SC_BAD_REQUEST
+        else if (statusCode == Response.Status.BAD_REQUEST.getStatusCode()) {
+            ex = new BadRequestException();
+        } // 4. All other codes are mapped to runtime exception with HTTP code information
+        else {
+            ex = new WebServiceException(String.format("Remote exception with status code: %s",
+                    Response.Status.fromStatusCode(statusCode).name()));
+        }
+        LOG.error("Exception thrown by REST methods: " + ex.getMessage(), ex);
+        return ex;
+    }
+
+    private SyncopeClientCompositeException checkSyncopeClientCompositeException(final Response response) {
+        List<Object> exTypesInHeaders = response.getHeaders().get(RESTHeaders.ERROR_CODE);
+        if (exTypesInHeaders == null) {
+            LOG.debug("No " + RESTHeaders.ERROR_CODE + " provided");
+            return null;
+        }
+
+        final SyncopeClientCompositeException compException = SyncopeClientException.buildComposite();
+
+        final Set<String> handledExceptions = new HashSet<String>();
+        for (Object exceptionTypeValue : exTypesInHeaders) {
+            final String exTypeAsString = (String) exceptionTypeValue;
+            ClientExceptionType exceptionType = null;
+            try {
+                exceptionType = ClientExceptionType.fromHeaderValue(exTypeAsString);
+            } catch (IllegalArgumentException e) {
+                LOG.error("Unexpected value of " + RESTHeaders.ERROR_CODE + ": " + exTypeAsString, e);
+            }
+            if (exceptionType != null) {
+                handledExceptions.add(exTypeAsString);
+
+                final SyncopeClientException clientException = SyncopeClientException.build(exceptionType);
+
+                if (response.getHeaders().get(RESTHeaders.ERROR_INFO) != null
+                        && !response.getHeaders().get(RESTHeaders.ERROR_INFO).isEmpty()) {
+
+                    for (Object value : response.getHeaders().get(RESTHeaders.ERROR_INFO)) {
+                        final String element = value.toString();
+                        if (element.startsWith(exceptionType.getHeaderValue())) {
+                            clientException.getElements().add(StringUtils.substringAfter(value.toString(), ":"));
+                        }
+                    }
+                }
+                compException.addException(clientException);
+            }
+        }
+
+        exTypesInHeaders.removeAll(handledExceptions);
+        if (!exTypesInHeaders.isEmpty()) {
+            LOG.error("Unmanaged exceptions: " + exTypesInHeaders);
+        }
+
+        if (compException.hasExceptions()) {
+            return compException;
+        }
+
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/lib/src/main/java/org/apache/syncope/client/lib/RestClientFactoryBean.java
----------------------------------------------------------------------
diff --git a/client/lib/src/main/java/org/apache/syncope/client/lib/RestClientFactoryBean.java b/client/lib/src/main/java/org/apache/syncope/client/lib/RestClientFactoryBean.java
new file mode 100644
index 0000000..4d77f2f
--- /dev/null
+++ b/client/lib/src/main/java/org/apache/syncope/client/lib/RestClientFactoryBean.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.lib;
+
+import javax.ws.rs.core.MediaType;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
+import org.apache.cxf.jaxrs.client.WebClient;
+
+/**
+ * Provides shortcuts for creating JAX-RS service instances via CXF's <tt>JAXRSClientFactoryBean</tt>.
+ */
+public class RestClientFactoryBean extends JAXRSClientFactoryBean {
+
+    /**
+     * Creates an anonymous instance of the given service class, for the given content type.
+     *
+     * @param <T> any service class
+     * @param serviceClass service class reference
+     * @param mediaType XML or JSON are suppoorted
+     * @return anonymous service instance of the given reference class
+     */
+    public <T> T createServiceInstance(final Class<T> serviceClass, final MediaType mediaType) {
+        return createServiceInstance(serviceClass, mediaType, null, null);
+    }
+
+    /**
+     * Creates an authenticated instance of the given service class, for the given content type.
+     *
+     * @param <T> any service class
+     * @param serviceClass service class reference
+     * @param mediaType XML or JSON are suppoorted
+     * @param username username for REST authentication
+     * @param password password for REST authentication
+     * @return anonymous service instance of the given reference class
+     */
+    public <T> T createServiceInstance(
+            final Class<T> serviceClass, final MediaType mediaType, final String username, final String password) {
+
+        if (StringUtils.isNotBlank(username)) {
+            setUsername(username);
+        }
+        if (StringUtils.isNotBlank(password)) {
+            setPassword(password);
+        }
+        setServiceClass(serviceClass);
+        final T serviceInstance = create(serviceClass);
+        WebClient.client(serviceInstance).type(mediaType).accept(mediaType);
+        return serviceInstance;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java
----------------------------------------------------------------------
diff --git a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java
new file mode 100644
index 0000000..43c2fea
--- /dev/null
+++ b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java
@@ -0,0 +1,214 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.lib;
+
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.MediaType;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.syncope.common.lib.search.OrderByClauseBuilder;
+import org.apache.syncope.common.lib.search.RoleFiqlSearchConditionBuilder;
+import org.apache.syncope.common.lib.search.UserFiqlSearchConditionBuilder;
+import org.apache.syncope.common.rest.api.Preference;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+
+/**
+ * Entry point for client access to all REST services exposed by Syncope core; obtain instances via
+ * {@link SyncopeClientFactoryBean}.
+ */
+public class SyncopeClient {
+
+    private final MediaType mediaType;
+
+    private final RestClientFactoryBean restClientFactory;
+
+    private final String username;
+
+    private final String password;
+
+    public SyncopeClient(final MediaType mediaType, final RestClientFactoryBean restClientFactory,
+            final String username, final String password) {
+
+        this.mediaType = mediaType;
+        this.restClientFactory = restClientFactory;
+        this.username = username;
+        this.password = password;
+    }
+
+    /**
+     * Returns a new instance of <tt>UserFiqlSearchConditionBuilder</tt>, for assisted building of FIQL queries.
+     *
+     * @return default instance of <tt>UserFiqlSearchConditionBuilder</tt>
+     */
+    public static UserFiqlSearchConditionBuilder getUserSearchConditionBuilder() {
+        return new UserFiqlSearchConditionBuilder();
+    }
+
+    /**
+     * Returns a new instance of <tt>RoleFiqlSearchConditionBuilder</tt>, for assisted building of FIQL queries.
+     *
+     * @return default instance of <tt>RoleFiqlSearchConditionBuilder</tt>
+     */
+    public static RoleFiqlSearchConditionBuilder getRoleSearchConditionBuilder() {
+        return new RoleFiqlSearchConditionBuilder();
+    }
+
+    /**
+     * Returns a new instance of <tt>OrderByClauseBuilder</tt>, for assisted building of <tt>orderby</tt> clauses.
+     *
+     * @return default instance of <tt>OrderByClauseBuilder</tt>
+     */
+    public static OrderByClauseBuilder getOrderByClauseBuilder() {
+        return new OrderByClauseBuilder();
+    }
+
+    /**
+     * Creates an instance of the given service class, with configured content type and authentication.
+     *
+     * @param <T> any service class
+     * @param serviceClass service class reference
+     * @return service instance of the given reference class
+     */
+    public <T> T getService(final Class<T> serviceClass) {
+        return restClientFactory.createServiceInstance(serviceClass, mediaType, username, password);
+    }
+
+    /**
+     * Sets the given header on the give service instance.
+     *
+     * @param <T> any service class
+     * @param service service class instance
+     * @param key HTTP header key
+     * @param values HTTP header values
+     * @return given service instance, with given header set
+     */
+    public <T> T header(final T service, final String key, final Object... values) {
+        WebClient.client(service).header(key, values);
+        return service;
+    }
+
+    /**
+     * Creates an instance of the given service class and sets the given header.
+     *
+     * @param <T> any service class
+     * @param serviceClass service class reference
+     * @param key HTTP header key
+     * @param values HTTP header values
+     * @return service instance of the given reference class, with given header set
+     */
+    public <T> T header(final Class<T> serviceClass, final String key, final Object... values) {
+        return header(getService(serviceClass), key, values);
+    }
+
+    /**
+     * Sets the <tt>Prefer</tt> header on the give service instance.
+     *
+     * @param <T> any service class
+     * @param service service class instance
+     * @param preference preference to be set via <tt>Prefer</tt> header
+     * @return given service instance, with <tt>Prefer</tt> header set
+     */
+    public <T> T prefer(final T service, final Preference preference) {
+        return header(service, RESTHeaders.PREFER, preference.toString());
+    }
+
+    /**
+     * Creates an instance of the given service class, with <tt>Prefer</tt> header set.
+     *
+     * @param <T> any service class
+     * @param serviceClass service class reference
+     * @param preference preference to be set via <tt>Prefer</tt> header
+     * @return service instance of the given reference class, with <tt>Prefer</tt> header set
+     */
+    public <T> T prefer(final Class<T> serviceClass, final Preference preference) {
+        return header(serviceClass, RESTHeaders.PREFER, preference.toString());
+    }
+
+    /**
+     * Sets the <tt>If-Match</tt> or <tt>If-None-Match</tt> header on the given service instance.
+     *
+     * @param <T> any service class
+     * @param service service class instance
+     * @param etag ETag value
+     * @param ifNot if true then <tt>If-None-Match</tt> is set, <tt>If-Match</tt> otherwise
+     * @return given service instance, with <tt>If-Match</tt> or <tt>If-None-Match</tt> set
+     */
+    private <T> T match(final T service, final EntityTag etag, final boolean ifNot) {
+        WebClient.client(service).match(etag, ifNot);
+        return service;
+    }
+
+    /**
+     * Sets the <tt>If-Match</tt> header on the given service instance.
+     *
+     * @param <T> any service class
+     * @param service service class instance
+     * @param etag ETag value
+     * @return given service instance, with <tt>If-Match</tt> set
+     */
+    public <T> T ifMatch(final T service, final EntityTag etag) {
+        return match(service, etag, false);
+    }
+
+    /**
+     * Creates an instance of the given service class, with <tt>If-Match</tt> header set.
+     *
+     * @param <T> any service class
+     * @param serviceClass service class reference
+     * @param etag ETag value
+     * @return given service instance, with <tt>If-Match</tt> set
+     */
+    public <T> T ifMatch(final Class<T> serviceClass, final EntityTag etag) {
+        return match(getService(serviceClass), etag, false);
+    }
+
+    /**
+     * Sets the <tt>If-None-Match</tt> header on the given service instance.
+     *
+     * @param <T> any service class
+     * @param service service class instance
+     * @param etag ETag value
+     * @return given service instance, with <tt>If-None-Match</tt> set
+     */
+    public <T> T ifNoneMatch(final T service, final EntityTag etag) {
+        return match(service, etag, true);
+    }
+
+    /**
+     * Creates an instance of the given service class, with <tt>If-None-Match</tt> header set.
+     *
+     * @param <T> any service class
+     * @param serviceClass service class reference
+     * @param etag ETag value
+     * @return given service instance, with <tt>If-None-Match</tt> set
+     */
+    public <T> T ifNoneMatch(final Class<T> serviceClass, final EntityTag etag) {
+        return match(getService(serviceClass), etag, true);
+    }
+
+    /**
+     * Fetches <tt>ETag</tt> header value from latest service run (if available).
+     *
+     * @param <T> any service class
+     * @param service service class instance
+     * @return <tt>ETag</tt> header value from latest service run (if available)
+     */
+    public <T> EntityTag getLatestEntityTag(final T service) {
+        return WebClient.client(service).getResponse().getEntityTag();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
----------------------------------------------------------------------
diff --git a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
new file mode 100644
index 0000000..53e0fda
--- /dev/null
+++ b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.lib;
+
+import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.ws.rs.core.MediaType;
+import javax.xml.bind.Marshaller;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.cxf.feature.Feature;
+import org.apache.cxf.feature.LoggingFeature;
+import org.apache.cxf.jaxrs.provider.JAXBElementProvider;
+import org.apache.cxf.staxutils.DocumentDepthProperties;
+import org.apache.syncope.common.lib.to.AbstractPolicyTO;
+
+/**
+ * Factory bean for creating instances of {@link SyncopeClient}.
+ * Supports Spring-bean configuration and override via subclassing (see protected methods).
+ */
+public class SyncopeClientFactoryBean {
+
+    public enum ContentType {
+
+        JSON(MediaType.APPLICATION_JSON_TYPE),
+        XML(MediaType.APPLICATION_XML_TYPE);
+
+        private final MediaType mediaType;
+
+        private ContentType(final MediaType mediaType) {
+            this.mediaType = mediaType;
+        }
+
+        public MediaType getMediaType() {
+            return mediaType;
+        }
+
+        public static ContentType fromString(final String value) {
+            return StringUtils.isNotBlank(value) && value.equalsIgnoreCase(XML.getMediaType().toString())
+                    ? XML
+                    : JSON;
+        }
+    }
+
+    private JacksonJaxbJsonProvider jsonProvider;
+
+    @SuppressWarnings("rawtypes")
+    private JAXBElementProvider jaxbProvider;
+
+    private RestClientExceptionMapper exceptionMapper;
+
+    private String address;
+
+    private ContentType contentType;
+
+    private RestClientFactoryBean restClientFactoryBean;
+
+    protected JacksonJaxbJsonProvider defaultJsonProvider() {
+        return new JacksonJaxbJsonProvider();
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    protected JAXBElementProvider defaultJAXBProvider() {
+        JAXBElementProvider defaultJAXBProvider = new JAXBElementProvider();
+
+        DocumentDepthProperties depthProperties = new DocumentDepthProperties();
+        depthProperties.setInnerElementCountThreshold(500);
+        defaultJAXBProvider.setDepthProperties(depthProperties);
+
+        Map marshallerProperties = new HashMap();
+        marshallerProperties.put(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+        defaultJAXBProvider.setMarshallerProperties(marshallerProperties);
+
+        Map<String, String> collectionWrapperMap = new HashMap<String, String>();
+        collectionWrapperMap.put(AbstractPolicyTO.class.getName(), "policies");
+        defaultJAXBProvider.setCollectionWrapperMap(collectionWrapperMap);
+
+        return defaultJAXBProvider;
+    }
+
+    protected RestClientExceptionMapper defaultExceptionMapper() {
+        return new RestClientExceptionMapper();
+    }
+
+    protected RestClientFactoryBean defaultRestClientFactoryBean() {
+        RestClientFactoryBean defaultRestClientFactoryBean = new RestClientFactoryBean();
+
+        if (StringUtils.isBlank(address)) {
+            throw new IllegalArgumentException("Property 'address' is missing");
+        }
+        defaultRestClientFactoryBean.setAddress(address);
+
+        defaultRestClientFactoryBean.setThreadSafe(true);
+        defaultRestClientFactoryBean.setInheritHeaders(true);
+
+        List<Feature> features = new ArrayList<Feature>();
+        features.add(new LoggingFeature());
+        defaultRestClientFactoryBean.setFeatures(features);
+
+        List<Object> providers = new ArrayList<Object>(3);
+        providers.add(getJaxbProvider());
+        providers.add(getJsonProvider());
+        providers.add(getExceptionMapper());
+        defaultRestClientFactoryBean.setProviders(providers);
+
+        return defaultRestClientFactoryBean;
+    }
+
+    public JacksonJaxbJsonProvider getJsonProvider() {
+        return jsonProvider == null
+                ? defaultJsonProvider()
+                : jsonProvider;
+    }
+
+    public void setJsonProvider(final JacksonJaxbJsonProvider jsonProvider) {
+        this.jsonProvider = jsonProvider;
+    }
+
+    public JAXBElementProvider getJaxbProvider() {
+        return jaxbProvider == null
+                ? defaultJAXBProvider()
+                : jaxbProvider;
+    }
+
+    public SyncopeClientFactoryBean setJaxbProvider(final JAXBElementProvider jaxbProvider) {
+        this.jaxbProvider = jaxbProvider;
+        return this;
+    }
+
+    public RestClientExceptionMapper getExceptionMapper() {
+        return exceptionMapper == null
+                ? defaultExceptionMapper()
+                : exceptionMapper;
+    }
+
+    public SyncopeClientFactoryBean setExceptionMapper(final RestClientExceptionMapper exceptionMapper) {
+        this.exceptionMapper = exceptionMapper;
+        return this;
+    }
+
+    public String getAddress() {
+        return address;
+    }
+
+    public SyncopeClientFactoryBean setAddress(final String address) {
+        this.address = address;
+        return this;
+    }
+
+    public ContentType getContentType() {
+        return contentType == null
+                ? ContentType.JSON
+                : contentType;
+    }
+
+    public SyncopeClientFactoryBean setContentType(final ContentType contentType) {
+        this.contentType = contentType;
+        return this;
+    }
+
+    public SyncopeClientFactoryBean setContentType(final String contentType) {
+        this.contentType = ContentType.fromString(contentType);
+        return this;
+    }
+
+    public RestClientFactoryBean getRestClientFactoryBean() {
+        return restClientFactoryBean == null
+                ? defaultRestClientFactoryBean()
+                : restClientFactoryBean;
+    }
+
+    public SyncopeClientFactoryBean setRestClientFactoryBean(final RestClientFactoryBean restClientFactoryBean) {
+        this.restClientFactoryBean = restClientFactoryBean;
+        return this;
+    }
+
+    public SyncopeClient createAnonymous() {
+        return create(null, null);
+    }
+
+    public SyncopeClient create(final String username, final String password) {
+        return new SyncopeClient(getContentType().getMediaType(), getRestClientFactoryBean(), username, password);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/pom.xml
----------------------------------------------------------------------
diff --git a/client/pom.xml b/client/pom.xml
index f618315..78bfcbd 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -31,89 +31,12 @@ under the License.
   <description>Apache Syncope Client</description>
   <groupId>org.apache.syncope</groupId>
   <artifactId>syncope-client</artifactId>
-  <packaging>bundle</packaging>
+  <packaging>pom</packaging>
 
-  <distributionManagement>
-    <site>
-      <id>syncope.website</id>
-      <name>Apache Syncope website</name>
-      <url>${site.deploymentBaseUrl}/${project.artifactId}</url>
-    </site>
-  </distributionManagement>
+  <modules>
+    <module>lib</module>
+    <module>console</module>
+    <module>cli</module>
+  </modules>
 
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.syncope</groupId>
-      <artifactId>syncope-common</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-
-    <dependency>
-      <groupId>javax.ws.rs</groupId>
-      <artifactId>javax.ws.rs-api</artifactId>
-    </dependency>
-
-    <dependency>
-      <groupId>org.apache.cxf</groupId>
-      <artifactId>cxf-rt-rs-client</artifactId>
-    </dependency>
-
-    <dependency>
-      <groupId>com.fasterxml.jackson.jaxrs</groupId>
-      <artifactId>jackson-jaxrs-json-provider</artifactId>
-    </dependency>  
-
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-api</artifactId>
-    </dependency>
-  </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Bundle-Name>${project.name}</Bundle-Name>
-            <Bundle-SymbolicName>org.apache.syncope.client</Bundle-SymbolicName>
-            <Bundle-Version>${project.version}</Bundle-Version>
-            <Export-Package>
-              org.apache.syncope.client*;version=${project.version};-split-package:=merge-first
-            </Export-Package>
-            <Import-Package>
-              com.fasterxml.jackson*;version="[2.2.2,2.3)",
-              org.slf4j;resolution:=optional,
-              *
-            </Import-Package>
-          </instructions>
-        </configuration>
-      </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-checkstyle-plugin</artifactId>
-      </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-pmd-plugin</artifactId>
-      </plugin>
-    </plugins>
-
-    <resources>
-      <resource>
-        <directory>..</directory>
-        <targetPath>META-INF</targetPath>
-        <includes>
-          <include>LICENSE</include>
-          <include>NOTICE</include>
-        </includes>
-      </resource>
-      <resource>
-        <directory>src/main/resources/META-INF</directory>
-        <targetPath>META-INF</targetPath>
-      </resource>
-    </resources>
-  </build>
 </project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/src/main/java/org/apache/syncope/client/SyncopeClient.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/syncope/client/SyncopeClient.java b/client/src/main/java/org/apache/syncope/client/SyncopeClient.java
deleted file mode 100644
index f955951..0000000
--- a/client/src/main/java/org/apache/syncope/client/SyncopeClient.java
+++ /dev/null
@@ -1,305 +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.client;
-
-import javax.ws.rs.core.EntityTag;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import org.apache.cxf.jaxrs.client.WebClient;
-import org.apache.syncope.client.rest.RestClientFactoryBean;
-import org.apache.syncope.common.search.OrderByClauseBuilder;
-import org.apache.syncope.common.search.RoleFiqlSearchConditionBuilder;
-import org.apache.syncope.common.search.UserFiqlSearchConditionBuilder;
-import org.apache.syncope.common.services.RouteService;
-import org.apache.syncope.common.services.UserSelfService;
-import org.apache.syncope.common.services.WorkflowService;
-import org.apache.syncope.common.types.Preference;
-import org.apache.syncope.common.types.RESTHeaders;
-import org.apache.syncope.common.types.SubjectType;
-
-/**
- * Entry point for client access to all REST services exposed by Syncope core; obtain instances via
- * <tt>SyncopeClientFactoryBean</tt>.
- *
- * @see SyncopeClientFactoryBean
- */
-public class SyncopeClient {
-
-    private final MediaType mediaType;
-
-    private final RestClientFactoryBean restClientFactory;
-
-    private final String username;
-
-    private final String password;
-
-    public SyncopeClient(final MediaType mediaType, final RestClientFactoryBean restClientFactory,
-            final String username, final String password) {
-
-        this.mediaType = mediaType;
-        this.restClientFactory = restClientFactory;
-        this.username = username;
-        this.password = password;
-    }
-
-    /**
-     * Returns a new instance of <tt>UserFiqlSearchConditionBuilder</tt>, for assisted building of FIQL queries.
-     *
-     * @return default instance of <tt>UserFiqlSearchConditionBuilder</tt>
-     */
-    public static UserFiqlSearchConditionBuilder getUserSearchConditionBuilder() {
-        return new UserFiqlSearchConditionBuilder();
-    }
-
-    /**
-     * Returns a new instance of <tt>RoleFiqlSearchConditionBuilder</tt>, for assisted building of FIQL queries.
-     *
-     * @return default instance of <tt>RoleFiqlSearchConditionBuilder</tt>
-     */
-    public static RoleFiqlSearchConditionBuilder getRoleSearchConditionBuilder() {
-        return new RoleFiqlSearchConditionBuilder();
-    }
-
-    /**
-     * Returns a new instance of <tt>OrderByClauseBuilder</tt>, for assisted building of <tt>orderby</tt> clauses.
-     *
-     * @return default instance of <tt>OrderByClauseBuilder</tt>
-     */
-    public static OrderByClauseBuilder getOrderByClauseBuilder() {
-        return new OrderByClauseBuilder();
-    }
-
-    /**
-     * Creates an instance of the given service class, with configured content type and authentication.
-     *
-     * @param <T> any service class
-     * @param serviceClass service class reference
-     * @return service instance of the given reference class
-     */
-    public <T> T getService(final Class<T> serviceClass) {
-        return restClientFactory.createServiceInstance(serviceClass, mediaType, username, password);
-    }
-
-    /**
-     * Sets the given header on the give service instance.
-     *
-     * @param <T> any service class
-     * @param service service class instance
-     * @param key HTTP header key
-     * @param values HTTP header values
-     * @return given service instance, with given header set
-     */
-    public <T> T header(final T service, final String key, final Object... values) {
-        WebClient.client(service).header(key, values);
-        return service;
-    }
-
-    /**
-     * Creates an instance of the given service class and sets the given header.
-     *
-     * @param <T> any service class
-     * @param serviceClass service class reference
-     * @param key HTTP header key
-     * @param values HTTP header values
-     * @return service instance of the given reference class, with given header set
-     */
-    public <T> T header(final Class<T> serviceClass, final String key, final Object... values) {
-        return header(getService(serviceClass), key, values);
-    }
-
-    /**
-     * Sets the <tt>Prefer</tt> header on the give service instance.
-     *
-     * @param <T> any service class
-     * @param service service class instance
-     * @param preference preference to be set via <tt>Prefer</tt> header
-     * @return given service instance, with <tt>Prefer</tt> header set
-     */
-    public <T> T prefer(final T service, final Preference preference) {
-        return header(service, RESTHeaders.PREFER, preference.toString());
-    }
-
-    /**
-     * Creates an instance of the given service class, with <tt>Prefer</tt> header set.
-     *
-     * @param <T> any service class
-     * @param serviceClass service class reference
-     * @param preference preference to be set via <tt>Prefer</tt> header
-     * @return service instance of the given reference class, with <tt>Prefer</tt> header set
-     */
-    public <T> T prefer(final Class<T> serviceClass, final Preference preference) {
-        return header(serviceClass, RESTHeaders.PREFER, preference.toString());
-    }
-
-    /**
-     * Sets the <tt>If-Match</tt> or <tt>If-None-Match</tt> header on the given service instance.
-     *
-     * @param <T> any service class
-     * @param service service class instance
-     * @param etag ETag value
-     * @param ifNot if true then <tt>If-None-Match</tt> is set, <tt>If-Match</tt> otherwise
-     * @return given service instance, with <tt>If-Match</tt> or <tt>If-None-Match</tt> set
-     */
-    private <T> T match(final T service, final EntityTag etag, final boolean ifNot) {
-        WebClient.client(service).match(etag, ifNot);
-        return service;
-    }
-
-    /**
-     * Sets the <tt>If-Match</tt> header on the given service instance.
-     *
-     * @param <T> any service class
-     * @param service service class instance
-     * @param etag ETag value
-     * @return given service instance, with <tt>If-Match</tt> set
-     */
-    public <T> T ifMatch(final T service, final EntityTag etag) {
-        return match(service, etag, false);
-    }
-
-    /**
-     * Creates an instance of the given service class, with <tt>If-Match</tt> header set.
-     *
-     * @param <T> any service class
-     * @param serviceClass service class reference
-     * @param etag ETag value
-     * @return given service instance, with <tt>If-Match</tt> set
-     */
-    public <T> T ifMatch(final Class<T> serviceClass, final EntityTag etag) {
-        return match(getService(serviceClass), etag, false);
-    }
-
-    /**
-     * Sets the <tt>If-None-Match</tt> header on the given service instance.
-     *
-     * @param <T> any service class
-     * @param service service class instance
-     * @param etag ETag value
-     * @return given service instance, with <tt>If-None-Match</tt> set
-     */
-    public <T> T ifNoneMatch(final T service, final EntityTag etag) {
-        return match(service, etag, true);
-    }
-
-    /**
-     * Creates an instance of the given service class, with <tt>If-None-Match</tt> header set.
-     *
-     * @param <T> any service class
-     * @param serviceClass service class reference
-     * @param etag ETag value
-     * @return given service instance, with <tt>If-None-Match</tt> set
-     */
-    public <T> T ifNoneMatch(final Class<T> serviceClass, final EntityTag etag) {
-        return match(getService(serviceClass), etag, true);
-    }
-
-    /**
-     * Checks whether self-registration is allowed by calling <tt>UserSelfService</tt>'s options.
-     *
-     * @return whether self-registration is allowed
-     * @see UserSelfService#getOptions()
-     */
-    public boolean isSelfRegAllowed() {
-        return Boolean.valueOf(restClientFactory.createServiceInstance(UserSelfService.class, mediaType, null, null).
-                getOptions().getHeaderString(RESTHeaders.SELFREG_ALLOWED));
-    }
-
-    /**
-     * Checks whether password reset is allowed by calling <tt>UserSelfService</tt>'s options.
-     *
-     * @return whether password reset is allowed
-     * @see UserSelfService#getOptions()
-     */
-    public boolean isPwdResetAllowed() {
-        return Boolean.valueOf(restClientFactory.createServiceInstance(UserSelfService.class, mediaType, null, null).
-                getOptions().getHeaderString(RESTHeaders.PWDRESET_ALLOWED));
-    }
-
-    /**
-     * Checks whether password reset requires security question by calling <tt>UserSelfService</tt>'s options.
-     *
-     * @return whether password reset requires security question
-     * @see UserSelfService#getOptions()
-     */
-    public boolean isPwdResetRequiringSecurityQuestions() {
-        return Boolean.valueOf(restClientFactory.createServiceInstance(UserSelfService.class, mediaType, null, null).
-                getOptions().getHeaderString(RESTHeaders.PWDRESET_NEEDS_SECURITYQUESTIONS));
-    }
-
-    /**
-     * Checks whether Activiti workflow is enabled for users / roles, by calling <tt>WorkflowService</tt>'s options.
-     *
-     * @param subjectType user / role
-     * @return whether Activiti workflow is enabled for given attributable type
-     * @see WorkflowService#getOptions(org.apache.syncope.common.types.SubjectType)
-     */
-    public boolean isActivitiEnabledFor(final SubjectType subjectType) {
-        Response options = getService(WorkflowService.class).getOptions(subjectType);
-
-        boolean result;
-        switch (subjectType) {
-            case ROLE:
-                result = Boolean.valueOf(options.getHeaderString(RESTHeaders.ACTIVITI_ROLE_ENABLED));
-                break;
-
-            case USER:
-            default:
-                result = Boolean.valueOf(options.getHeaderString(RESTHeaders.ACTIVITI_USER_ENABLED));
-                break;
-        }
-
-        return result;
-    }
-    
-    /**
-     * Checks whether Camel is enabled for users / roles, by calling <tt>RouteService</tt>'s options.
-     *
-     * @param subjectType user / role
-     * @return whether Camel Provisioning is enabled for given attributable type
-     * @see RouteService#getOptions(org.apache.syncope.common.types.SubjectType)
-     */
-    public boolean isCamelEnabledFor(final SubjectType subjectType) {
-        Response options = getService(RouteService.class).getOptions(subjectType);
-
-        boolean result;
-        switch (subjectType) {
-            case ROLE:
-                result = Boolean.valueOf(options.getHeaderString(RESTHeaders.CAMEL_ROLE_PROVISIONING_MANAGER));
-                break;
-
-            case USER:
-            default:
-                result = Boolean.valueOf(options.getHeaderString(RESTHeaders.CAMEL_USER_PROVISIONING_MANAGER));
-                break;
-        }
-
-        return result;
-    }
-
-    /**
-     * Fetches <tt>ETag</tt> header value from latest service run (if available).
-     *
-     * @param <T> any service class
-     * @param service service class instance
-     * @return <tt>ETag</tt> header value from latest service run (if available)
-     */
-    public <T> EntityTag getLatestEntityTag(final T service) {
-        return WebClient.client(service).getResponse().getEntityTag();
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/src/main/java/org/apache/syncope/client/SyncopeClientFactoryBean.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/syncope/client/SyncopeClientFactoryBean.java b/client/src/main/java/org/apache/syncope/client/SyncopeClientFactoryBean.java
deleted file mode 100644
index 234625b..0000000
--- a/client/src/main/java/org/apache/syncope/client/SyncopeClientFactoryBean.java
+++ /dev/null
@@ -1,204 +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.client;
-
-import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import javax.ws.rs.core.MediaType;
-import javax.xml.bind.Marshaller;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.cxf.feature.Feature;
-import org.apache.cxf.feature.LoggingFeature;
-import org.apache.cxf.jaxrs.provider.JAXBElementProvider;
-import org.apache.cxf.staxutils.DocumentDepthProperties;
-import org.apache.syncope.client.rest.RestClientExceptionMapper;
-import org.apache.syncope.client.rest.RestClientFactoryBean;
-import org.apache.syncope.common.to.AbstractPolicyTO;
-
-/**
- * Factory bean for creating instances of <tt>SyncopeClient</tt>.
- * Supports Spring-bean configuration and override via subclassing (see protected methods).
- */
-public class SyncopeClientFactoryBean {
-
-    public enum ContentType {
-
-        JSON(MediaType.APPLICATION_JSON_TYPE),
-        XML(MediaType.APPLICATION_XML_TYPE);
-
-        private final MediaType mediaType;
-
-        private ContentType(final MediaType mediaType) {
-            this.mediaType = mediaType;
-        }
-
-        public MediaType getMediaType() {
-            return mediaType;
-        }
-
-        public static ContentType fromString(final String value) {
-            return StringUtils.isNotBlank(value) && value.equalsIgnoreCase(XML.getMediaType().toString())
-                    ? XML
-                    : JSON;
-        }
-    }
-
-    private JacksonJaxbJsonProvider jsonProvider;
-
-    @SuppressWarnings("rawtypes")
-    private JAXBElementProvider jaxbProvider;
-
-    private RestClientExceptionMapper exceptionMapper;
-
-    private String address;
-
-    private ContentType contentType;
-
-    private RestClientFactoryBean restClientFactoryBean;
-
-    protected JacksonJaxbJsonProvider defaultJsonProvider() {
-        return new JacksonJaxbJsonProvider();
-    }
-
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    protected JAXBElementProvider defaultJAXBProvider() {
-        JAXBElementProvider defaultJAXBProvider = new JAXBElementProvider();
-
-        DocumentDepthProperties depthProperties = new DocumentDepthProperties();
-        depthProperties.setInnerElementCountThreshold(500);
-        defaultJAXBProvider.setDepthProperties(depthProperties);
-
-        Map marshallerProperties = new HashMap();
-        marshallerProperties.put(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
-        defaultJAXBProvider.setMarshallerProperties(marshallerProperties);
-
-        Map<String, String> collectionWrapperMap = new HashMap<String, String>();
-        collectionWrapperMap.put(AbstractPolicyTO.class.getName(), "policies");
-        defaultJAXBProvider.setCollectionWrapperMap(collectionWrapperMap);
-
-        return defaultJAXBProvider;
-    }
-
-    protected RestClientExceptionMapper defaultExceptionMapper() {
-        return new RestClientExceptionMapper();
-    }
-
-    protected RestClientFactoryBean defaultRestClientFactoryBean() {
-        RestClientFactoryBean defaultRestClientFactoryBean = new RestClientFactoryBean();
-
-        if (StringUtils.isBlank(address)) {
-            throw new IllegalArgumentException("Property 'address' is missing");
-        }
-        defaultRestClientFactoryBean.setAddress(address);
-
-        defaultRestClientFactoryBean.setThreadSafe(true);
-        defaultRestClientFactoryBean.setInheritHeaders(true);
-
-        List<Feature> features = new ArrayList<Feature>();
-        features.add(new LoggingFeature());
-        defaultRestClientFactoryBean.setFeatures(features);
-
-        List<Object> providers = new ArrayList<Object>(3);
-        providers.add(getJaxbProvider());
-        providers.add(getJsonProvider());
-        providers.add(getExceptionMapper());
-        defaultRestClientFactoryBean.setProviders(providers);
-
-        return defaultRestClientFactoryBean;
-    }
-
-    public JacksonJaxbJsonProvider getJsonProvider() {
-        return jsonProvider == null
-                ? defaultJsonProvider()
-                : jsonProvider;
-    }
-
-    public void setJsonProvider(final JacksonJaxbJsonProvider jsonProvider) {
-        this.jsonProvider = jsonProvider;
-    }
-
-    public JAXBElementProvider getJaxbProvider() {
-        return jaxbProvider == null
-                ? defaultJAXBProvider()
-                : jaxbProvider;
-    }
-
-    public SyncopeClientFactoryBean setJaxbProvider(final JAXBElementProvider jaxbProvider) {
-        this.jaxbProvider = jaxbProvider;
-        return this;
-    }
-
-    public RestClientExceptionMapper getExceptionMapper() {
-        return exceptionMapper == null
-                ? defaultExceptionMapper()
-                : exceptionMapper;
-    }
-
-    public SyncopeClientFactoryBean setExceptionMapper(final RestClientExceptionMapper exceptionMapper) {
-        this.exceptionMapper = exceptionMapper;
-        return this;
-    }
-
-    public String getAddress() {
-        return address;
-    }
-
-    public SyncopeClientFactoryBean setAddress(final String address) {
-        this.address = address;
-        return this;
-    }
-
-    public ContentType getContentType() {
-        return contentType == null
-                ? ContentType.JSON
-                : contentType;
-    }
-
-    public SyncopeClientFactoryBean setContentType(final ContentType contentType) {
-        this.contentType = contentType;
-        return this;
-    }
-
-    public SyncopeClientFactoryBean setContentType(final String contentType) {
-        this.contentType = ContentType.fromString(contentType);
-        return this;
-    }
-
-    public RestClientFactoryBean getRestClientFactoryBean() {
-        return restClientFactoryBean == null
-                ? defaultRestClientFactoryBean()
-                : restClientFactoryBean;
-    }
-
-    public SyncopeClientFactoryBean setRestClientFactoryBean(final RestClientFactoryBean restClientFactoryBean) {
-        this.restClientFactoryBean = restClientFactoryBean;
-        return this;
-    }
-
-    public SyncopeClient createAnonymous() {
-        return create(null, null);
-    }
-
-    public SyncopeClient create(final String username, final String password) {
-        return new SyncopeClient(getContentType().getMediaType(), getRestClientFactoryBean(), username, password);
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/src/main/java/org/apache/syncope/client/rest/RestClientExceptionMapper.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/syncope/client/rest/RestClientExceptionMapper.java b/client/src/main/java/org/apache/syncope/client/rest/RestClientExceptionMapper.java
deleted file mode 100644
index 1a9d2ef..0000000
--- a/client/src/main/java/org/apache/syncope/client/rest/RestClientExceptionMapper.java
+++ /dev/null
@@ -1,126 +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.client.rest;
-
-import java.security.AccessControlException;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import javax.ws.rs.BadRequestException;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.ExceptionMapper;
-import javax.ws.rs.ext.Provider;
-import javax.xml.ws.WebServiceException;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.cxf.jaxrs.client.ResponseExceptionMapper;
-import org.apache.syncope.common.types.ClientExceptionType;
-import org.apache.syncope.common.types.RESTHeaders;
-import org.apache.syncope.common.SyncopeClientCompositeException;
-import org.apache.syncope.common.SyncopeClientException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Provider
-public class RestClientExceptionMapper implements ExceptionMapper<Exception>, ResponseExceptionMapper<Exception> {
-
-    private static final Logger LOG = LoggerFactory.getLogger(RestClientExceptionMapper.class);
-
-    @Override
-    public Response toResponse(final Exception exception) {
-        throw new UnsupportedOperationException(
-                "Call of toResponse() method is not expected in RestClientExceptionnMapper");
-    }
-
-    @Override
-    public Exception fromResponse(final Response response) {
-        final int statusCode = response.getStatus();
-        Exception ex;
-
-        // 1. Check for client (possibly composite) exception in HTTP header
-        SyncopeClientCompositeException scce = checkSyncopeClientCompositeException(response);
-        if (scce != null) {
-            if (scce.getExceptions().size() == 1) {
-                ex = scce.getExceptions().iterator().next();
-            } else {
-                ex = scce;
-            }
-        } // 2. Map SC_UNAUTHORIZED
-        else if (statusCode == Response.Status.UNAUTHORIZED.getStatusCode()) {
-            ex = new AccessControlException("Remote unauthorized exception");
-        } // 3. Map SC_BAD_REQUEST
-        else if (statusCode == Response.Status.BAD_REQUEST.getStatusCode()) {
-            ex = new BadRequestException();
-        } // 4. All other codes are mapped to runtime exception with HTTP code information
-        else {
-            ex = new WebServiceException(String.format("Remote exception with status code: %s",
-                    Response.Status.fromStatusCode(statusCode).name()));
-        }
-        LOG.error("Exception thrown by REST methods: " + ex.getMessage(), ex);
-        return ex;
-    }
-
-    private SyncopeClientCompositeException checkSyncopeClientCompositeException(final Response response) {
-        List<Object> exTypesInHeaders = response.getHeaders().get(RESTHeaders.ERROR_CODE);
-        if (exTypesInHeaders == null) {
-            LOG.debug("No " + RESTHeaders.ERROR_CODE + " provided");
-            return null;
-        }
-
-        final SyncopeClientCompositeException compException = SyncopeClientException.buildComposite();
-
-        final Set<String> handledExceptions = new HashSet<String>();
-        for (Object exceptionTypeValue : exTypesInHeaders) {
-            final String exTypeAsString = (String) exceptionTypeValue;
-            ClientExceptionType exceptionType = null;
-            try {
-                exceptionType = ClientExceptionType.fromHeaderValue(exTypeAsString);
-            } catch (IllegalArgumentException e) {
-                LOG.error("Unexpected value of " + RESTHeaders.ERROR_CODE + ": " + exTypeAsString, e);
-            }
-            if (exceptionType != null) {
-                handledExceptions.add(exTypeAsString);
-
-                final SyncopeClientException clientException = SyncopeClientException.build(exceptionType);
-
-                if (response.getHeaders().get(RESTHeaders.ERROR_INFO) != null
-                        && !response.getHeaders().get(RESTHeaders.ERROR_INFO).isEmpty()) {
-
-                    for (Object value : response.getHeaders().get(RESTHeaders.ERROR_INFO)) {
-                        final String element = value.toString();
-                        if (element.startsWith(exceptionType.getHeaderValue())) {
-                            clientException.getElements().add(StringUtils.substringAfter(value.toString(), ":"));
-                        }
-                    }
-                }
-                compException.addException(clientException);
-            }
-        }
-
-        exTypesInHeaders.removeAll(handledExceptions);
-        if (!exTypesInHeaders.isEmpty()) {
-            LOG.error("Unmanaged exceptions: " + exTypesInHeaders);
-        }
-
-        if (compException.hasExceptions()) {
-            return compException;
-        }
-
-        return null;
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/src/main/java/org/apache/syncope/client/rest/RestClientFactoryBean.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/syncope/client/rest/RestClientFactoryBean.java b/client/src/main/java/org/apache/syncope/client/rest/RestClientFactoryBean.java
deleted file mode 100644
index e10840a..0000000
--- a/client/src/main/java/org/apache/syncope/client/rest/RestClientFactoryBean.java
+++ /dev/null
@@ -1,67 +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.client.rest;
-
-import javax.ws.rs.core.MediaType;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
-import org.apache.cxf.jaxrs.client.WebClient;
-
-/**
- * Provides shortcuts for creating JAX-RS service instances via CXF's <tt>JAXRSClientFactoryBean</tt>.
- */
-public class RestClientFactoryBean extends JAXRSClientFactoryBean {
-
-    /**
-     * Creates an anonymous instance of the given service class, for the given content type.
-     *
-     * @param <T> any service class
-     * @param serviceClass service class reference
-     * @param mediaType XML or JSON are suppoorted
-     * @return anonymous service instance of the given reference class
-     */
-    public <T> T createServiceInstance(final Class<T> serviceClass, final MediaType mediaType) {
-        return createServiceInstance(serviceClass, mediaType, null, null);
-    }
-
-    /**
-     * Creates an authenticated instance of the given service class, for the given content type.
-     *
-     * @param <T> any service class
-     * @param serviceClass service class reference
-     * @param mediaType XML or JSON are suppoorted
-     * @param username username for REST authentication
-     * @param password password for REST authentication
-     * @return anonymous service instance of the given reference class
-     */
-    public <T> T createServiceInstance(
-            final Class<T> serviceClass, final MediaType mediaType, final String username, final String password) {
-
-        if (StringUtils.isNotBlank(username)) {
-            setUsername(username);
-        }
-        if (StringUtils.isNotBlank(password)) {
-            setPassword(password);
-        }
-        setServiceClass(serviceClass);
-        final T serviceInstance = create(serviceClass);
-        WebClient.client(serviceInstance).type(mediaType).accept(mediaType);
-        return serviceInstance;
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/src/main/resources/META-INF/cxf/org.apache.cxf.Logger
----------------------------------------------------------------------
diff --git a/client/src/main/resources/META-INF/cxf/org.apache.cxf.Logger b/client/src/main/resources/META-INF/cxf/org.apache.cxf.Logger
deleted file mode 100644
index 6e7bd36..0000000
--- a/client/src/main/resources/META-INF/cxf/org.apache.cxf.Logger
+++ /dev/null
@@ -1 +0,0 @@
-org.apache.cxf.common.logging.Slf4jLogger

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/pom.xml
----------------------------------------------------------------------
diff --git a/common/lib/pom.xml b/common/lib/pom.xml
new file mode 100644
index 0000000..2bdc6ea
--- /dev/null
+++ b/common/lib/pom.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.syncope</groupId>
+    <artifactId>syncope-common</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Common Lib</name>
+  <description>Apache Syncope Common Lib</description>
+  <groupId>org.apache.syncope.common</groupId>
+  <artifactId>syncope-common-lib</artifactId>
+  <packaging>jar</packaging>
+
+  <properties>
+    <rootpom.basedir>${basedir}/../..</rootpom.basedir>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>javax.ws.rs</groupId>
+      <artifactId>javax.ws.rs-api</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.cxf</groupId>
+      <artifactId>cxf-rt-rs-extension-search</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-annotations</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-pmd-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/common/lib/src/main/java/org/apache/syncope/common/lib/AbstractBaseBean.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/AbstractBaseBean.java b/common/lib/src/main/java/org/apache/syncope/common/lib/AbstractBaseBean.java
new file mode 100644
index 0000000..8a6d9c4
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/AbstractBaseBean.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib;
+
+import java.io.Serializable;
+import javax.xml.bind.annotation.XmlSeeAlso;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.ReportTO;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.to.UserTO;
+
+@XmlType
+// Reporting here only classes used via PagedResult
+@XmlSeeAlso({ AbstractTaskTO.class, ReportTO.class, RoleTO.class, UserTO.class })
+public abstract class AbstractBaseBean implements Serializable {
+
+    private static final long serialVersionUID = 3119542005279892164L;
+
+    @Override
+    public boolean equals(final Object obj) {
+        return EqualsBuilder.reflectionEquals(this, obj);
+    }
+
+    @Override
+    public int hashCode() {
+        return HashCodeBuilder.reflectionHashCode(this);
+    }
+
+    @Override
+    public String toString() {
+        return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
+    }
+}