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:07:11 UTC

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

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/SyncopeSession.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeSession.java b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeSession.java
new file mode 100644
index 0000000..fc7f7b9
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeSession.java
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console;
+
+import java.text.DateFormat;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.MediaType;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.lib.to.SyncopeTO;
+import org.apache.syncope.common.rest.api.service.SyncopeService;
+import org.apache.wicket.Session;
+import org.apache.wicket.authroles.authorization.strategies.role.Roles;
+import org.apache.wicket.protocol.http.WebApplication;
+import org.apache.wicket.protocol.http.WebSession;
+import org.apache.wicket.request.Request;
+import org.springframework.context.ApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+/**
+ * Custom Syncope Session class.
+ */
+public class SyncopeSession extends WebSession {
+
+    private static final long serialVersionUID = 7743446298924805872L;
+
+    public static final List<Locale> SUPPORTED_LOCALES = Arrays.asList(new Locale[] {
+        Locale.ENGLISH, Locale.ITALIAN, new Locale("pt", "BR") });
+
+    private String username;
+
+    private String password;
+
+    private String version;
+
+    private Roles roles = new Roles();
+
+    private final SyncopeClientFactoryBean clientFactory;
+
+    private final String anonymousUser;
+
+    private final String anonymousKey;
+
+    private final SyncopeTO syncopeTO;
+
+    private final Map<Integer, SyncopeClient> clients =
+            Collections.synchronizedMap(new HashMap<Integer, SyncopeClient>());
+
+    public static SyncopeSession get() {
+        return (SyncopeSession) Session.get();
+    }
+
+    public SyncopeSession(final Request request) {
+        super(request);
+
+        final ApplicationContext ctx = WebApplicationContextUtils.
+                getWebApplicationContext(WebApplication.get().getServletContext());
+
+        clientFactory = ctx.getBean(SyncopeClientFactoryBean.class).
+                setContentType(SyncopeClientFactoryBean.ContentType.JSON);
+        anonymousUser = ctx.getBean("anonymousUser", String.class);
+        anonymousKey = ctx.getBean("anonymousKey", String.class);
+
+        syncopeTO = clientFactory.create(anonymousUser, anonymousKey).getService(SyncopeService.class).info();
+    }
+
+    public SyncopeTO getSyncopeTO() {
+        return syncopeTO;
+    }
+
+    public void resetClients() {
+        clients.clear();
+    }
+
+    public <T> T getService(final Class<T> service) {
+        return getService(service, this.username, this.password);
+    }
+
+    public <T> T getService(final String etag, final Class<T> service) {
+        T serviceInstance = getService(service, this.username, this.password);
+        WebClient.client(serviceInstance).match(new EntityTag(etag), false);
+
+        return serviceInstance;
+    }
+
+    public <T> void resetClient(final Class<T> service) {
+        T serviceInstance = getService(service, this.username, this.password);
+        WebClient.client(serviceInstance).reset();
+    }
+
+    public <T> T getService(final MediaType mediaType, final Class<T> serviceClass) {
+        T service;
+
+        synchronized (clientFactory) {
+            SyncopeClientFactoryBean.ContentType preType = clientFactory.getContentType();
+
+            clientFactory.setContentType(SyncopeClientFactoryBean.ContentType.fromString(mediaType.toString()));
+            service = clientFactory.create(username, password).getService(serviceClass);
+            clientFactory.setContentType(preType);
+        }
+
+        return service;
+    }
+
+    public <T> T getAnonymousService(final Class<T> serviceClass) {
+        return getService(serviceClass, this.anonymousUser, this.anonymousKey);
+    }
+
+    public <T> T getService(final Class<T> serviceClass, final String username, final String password) {
+        final int clientKey = new HashCodeBuilder().append(username).append(password).toHashCode();
+
+        if (!clients.containsKey(clientKey)) {
+            clients.put(clientKey, clientFactory.create(username, password));
+        }
+
+        return clients.get(clientKey).getService(serviceClass);
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(final String username) {
+        this.username = username;
+    }
+
+    public void setPassword(final String password) {
+        this.password = password;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(final String version) {
+        this.version = version;
+    }
+
+    public void setEntitlements(final String[] entitlements) {
+        String[] defensiveCopy = entitlements.clone();
+        roles = new Roles(defensiveCopy);
+    }
+
+    public Roles getEntitlements() {
+        return roles;
+    }
+
+    public boolean isAuthenticated() {
+        return getUsername() != null;
+    }
+
+    public boolean hasAnyRole(final Roles roles) {
+        return this.roles.hasAnyRole(roles);
+    }
+
+    public DateFormat getDateFormat() {
+        final Locale locale = getLocale() == null ? Locale.ENGLISH : getLocale();
+
+        return DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/ActionTableCheckGroup.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/ActionTableCheckGroup.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/ActionTableCheckGroup.java
new file mode 100644
index 0000000..453e0c0
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/ActionTableCheckGroup.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+import java.util.Collection;
+import org.apache.wicket.markup.html.form.CheckGroup;
+import org.apache.wicket.model.IModel;
+
+public class ActionTableCheckGroup<T> extends CheckGroup<T> {
+
+    private static final long serialVersionUID = 1288270558573401394L;
+
+    public ActionTableCheckGroup(final String id, final Collection<T> collection) {
+        super(id, collection);
+    }
+
+    public ActionTableCheckGroup(final String id, final IModel<Collection<T>> model) {
+        super(id, model);
+    }
+
+    public boolean isCheckable(final T element) {
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/AttrLayoutType.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/AttrLayoutType.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/AttrLayoutType.java
new file mode 100644
index 0000000..87cc062
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/AttrLayoutType.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.syncope.common.lib.types.AttributableType;
+
+public enum AttrLayoutType {
+
+    ADMIN_USER("admin.user.layout", Mode.ADMIN, AttributableType.USER),
+    SELF_USER("self.user.layout", Mode.SELF, AttributableType.USER),
+    ADMIN_ROLE("admin.role.layout", Mode.ADMIN, AttributableType.ROLE),
+    SELF_ROLE("self.role.layout", Mode.SELF, AttributableType.ROLE),
+    ADMIN_MEMBERSHIP("admin.membership.layout", Mode.ADMIN, AttributableType.MEMBERSHIP),
+    SELF_MEMBERSHIP("self.membership.layout", Mode.SELF, AttributableType.MEMBERSHIP);
+
+    private final String confKey;
+
+    private final Mode mode;
+
+    private final AttributableType attrType;
+
+    AttrLayoutType(final String confKey, final Mode mode, final AttributableType attrType) {
+        this.confKey = confKey;
+        this.mode = mode;
+        this.attrType = attrType;
+    }
+
+    public String getConfKey() {
+        return confKey;
+    }
+
+    public Mode getMode() {
+        return mode;
+    }
+
+    public AttributableType getAttrType() {
+        return attrType;
+    }
+
+    public static List<String> confKeys() {
+        List<String> confKeys = new ArrayList<String>();
+        for (AttrLayoutType value : values()) {
+            confKeys.add(value.getConfKey());
+        }
+
+        return confKeys;
+    }
+
+    public static AttrLayoutType valueOf(final Mode mode, final AttributableType attrType) {
+        AttrLayoutType result = null;
+        if (mode == Mode.ADMIN) {
+            switch (attrType) {
+                case USER:
+                    result = ADMIN_USER;
+                    break;
+
+                case MEMBERSHIP:
+                    result = ADMIN_MEMBERSHIP;
+                    break;
+
+                case ROLE:
+                    result = ADMIN_ROLE;
+                    break;
+
+                default:
+            }
+        } else if (mode == Mode.SELF) {
+            switch (attrType) {
+                case USER:
+                    result = SELF_USER;
+                    break;
+
+                case MEMBERSHIP:
+                    result = SELF_MEMBERSHIP;
+                    break;
+
+                case ROLE:
+                    result = SELF_ROLE;
+                    break;
+
+                default:
+            }
+        }
+
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/AttributableDataProvider.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/AttributableDataProvider.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/AttributableDataProvider.java
new file mode 100644
index 0000000..91a797e
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/AttributableDataProvider.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.syncope.client.console.rest.AbstractSubjectRestClient;
+import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
+import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+
+public class AttributableDataProvider extends SortableDataProvider<AbstractAttributableTO, String> {
+
+    private static final long serialVersionUID = 6267494272884913376L;
+
+    private final SortableAttributableProviderComparator comparator;
+
+    private String fiql = null;
+
+    private final int paginatorRows;
+
+    private final boolean filtered;
+
+    private final AbstractSubjectRestClient restClient;
+
+    public AttributableDataProvider(final AbstractSubjectRestClient restClient,
+            final int paginatorRows, final boolean filtered) {
+
+        super();
+
+        this.restClient = restClient;
+        this.filtered = filtered;
+        this.paginatorRows = paginatorRows;
+
+        // default sorting
+        setSort("key", SortOrder.ASCENDING);
+
+        this.comparator = new SortableAttributableProviderComparator(this);
+    }
+
+    public void setFIQL(final String fiql) {
+        this.fiql = fiql;
+    }
+
+    @Override
+    public Iterator<? extends AbstractAttributableTO> iterator(final long first, final long count) {
+        List<? extends AbstractAttributableTO> result;
+
+        final int page = ((int) first / paginatorRows);
+
+        if (filtered) {
+            result = fiql == null
+                    ? Collections.<AbstractAttributableTO>emptyList()
+                    : restClient.search(fiql, (page < 0 ? 0 : page) + 1, paginatorRows, getSort());
+        } else {
+            result = restClient.list((page < 0 ? 0 : page) + 1, paginatorRows, getSort());
+        }
+
+        Collections.sort(result, comparator);
+        return result.iterator();
+    }
+
+    @Override
+    public long size() {
+        long result;
+
+        if (filtered) {
+            result = fiql == null
+                    ? 0
+                    : restClient.searchCount(fiql);
+        } else {
+            result = restClient.count();
+        }
+
+        return result;
+    }
+
+    @Override
+    public IModel<AbstractAttributableTO> model(final AbstractAttributableTO object) {
+        return new CompoundPropertyModel<>(object);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/CloseOnESCBehavior.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/CloseOnESCBehavior.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/CloseOnESCBehavior.java
new file mode 100644
index 0000000..2e62431
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/CloseOnESCBehavior.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxEventBehavior;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxCallListener;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+
+public class CloseOnESCBehavior extends AjaxEventBehavior {
+
+    private static final long serialVersionUID = 5826308247642534260L;
+
+    public CloseOnESCBehavior(String event) {
+        super(event);
+    }
+
+    @Override
+    protected void onEvent(final AjaxRequestTarget target) {
+        ModalWindow.closeCurrent(target);
+    }
+
+    @Override
+    protected void updateAjaxAttributes(final AjaxRequestAttributes attributes) {
+        super.updateAjaxAttributes(attributes);
+
+        attributes.getAjaxCallListeners().add(new AjaxCallListener() {
+
+            private static final long serialVersionUID = 7160235486520935153L;
+
+            @Override
+            public CharSequence getPrecondition(final Component aComponent) {
+                return " if(Wicket.Event.keyCode(attrs.event) != 27){return false;}";
+            }
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/ConnIdSpecialAttributeName.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/ConnIdSpecialAttributeName.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/ConnIdSpecialAttributeName.java
new file mode 100644
index 0000000..3533172
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/ConnIdSpecialAttributeName.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+public final class ConnIdSpecialAttributeName {
+
+    public static final String ENABLE = "__ENABLE__";
+
+    public static final String NAME = "__NAME__";
+
+    public static final String UID = "__UID__";
+
+    public static final String PASSWORD = "__PASSWORD__";
+
+    private ConnIdSpecialAttributeName() {
+        // private constructor for static utility class
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
new file mode 100644
index 0000000..8f06874
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+public final class Constants {
+
+    public static final String ON_CLICK = "onclick";
+
+    public static final String ON_CHANGE = "onchange";
+
+    public static final String ON_BLUR = "onblur";
+
+    public static final String PNG_EXT = ".png";
+
+    public static final String FEEDBACK = "feedback";
+
+    public static final String OPERATION_SUCCEEDED = "operation_succeeded";
+
+    public static final String OPERATION_ERROR = "operation_error";
+
+    public static final String SEARCH_ERROR = "search_error";
+
+    public static final String ERROR = "error";
+
+    public static final String PARAM_PASSWORD_RESET_TOKEN = "pwdResetToken";
+
+    public static final String PREF_USERS_DETAILS_VIEW = "users.details.view";
+
+    public static final String PREF_USERS_ATTRIBUTES_VIEW = "users.attributes.view";
+
+    public static final String PREF_USERS_DERIVED_ATTRIBUTES_VIEW = "users.derived.attributes.view";
+
+    public static final String PREF_USERS_VIRTUAL_ATTRIBUTES_VIEW = "users.virtual.attributes.view";
+
+    public static final String PREF_CONF_SCHEMA_PAGINATOR_ROWS = "conf.schema.paginator.rows";
+
+    public static final String PREF_USER_SCHEMA_PAGINATOR_ROWS = "user.schema.paginator.rows";
+
+    public static final String PREF_USER_DER_SCHEMA_PAGINATOR_ROWS = "user.derived.schema.paginator.rows";
+
+    public static final String PREF_USER_VIR_SCHEMA_PAGINATOR_ROWS = "user.virtual.schema.paginator.rows";
+
+    public static final String PREF_ROLE_SCHEMA_PAGINATOR_ROWS = "role.schema.paginator.rows";
+
+    public static final String PREF_ROLE_DER_SCHEMA_PAGINATOR_ROWS = "role.derived.schema.paginator.rows";
+
+    public static final String PREF_ROLE_VIR_SCHEMA_PAGINATOR_ROWS = "role.virtual.schema.paginator.rows";
+
+    public static final String PREF_MEMBERSHIP_SCHEMA_PAGINATOR_ROWS = "membership.schema.paginator.rows";
+
+    public static final String PREF_MEMBERSHIP_DER_SCHEMA_PAGINATOR_ROWS = "membership.derived.aschema.paginator.rows";
+
+    public static final String PREF_MEMBERSHIP_VIR_SCHEMA_PAGINATOR_ROWS = "membership.virtual.aschema.paginator.rows";
+
+    public static final String PREF_USERS_PAGINATOR_ROWS = "users.paginator.rows";
+
+    public static final String PREF_RESOURCES_PAGINATOR_ROWS = "resources.paginator.rows";
+
+    public static final String PREF_CONNECTORS_PAGINATOR_ROWS = "connectors.paginator.rows";
+
+    public static final String PREF_NOTIFICATION_PAGINATOR_ROWS = "notification.paginator.rows";
+
+    public static final String PREF_PROPAGATION_TASKS_PAGINATOR_ROWS = "proagationtasks.paginator.rows";
+
+    public static final String PREF_NOTIFICATION_TASKS_PAGINATOR_ROWS = "notificationtasks.paginator.rows";
+
+    public static final String PREF_SCHED_TASKS_PAGINATOR_ROWS = "schedtasks.paginator.rows";
+
+    public static final String PREF_SYNC_TASKS_PAGINATOR_ROWS = "synctasks.paginator.rows";
+
+    public static final String PREF_TODO_PAGINATOR_ROWS = "todo.paginator.rows";
+
+    public static final String PREF_REPORT_PAGINATOR_ROWS = "report.paginator.rows";
+
+    public static final String PAGEPARAM_CREATE = "CREATE";
+
+    public static final String PAGEPARAM_CURRENT_PAGE = "_current_page";
+
+    public static final String PREF_POLICY_PAGINATOR_ROWS = "policy.paginator.rows";
+
+    /**
+     * ConnId's GuardedString is not in the classpath.
+     */
+    public static final String GUARDED_STRING = "org.identityconnectors.common.security.GuardedString";
+
+    /**
+     * ConnId's GuardedByteArray is not in the classpath.
+     */
+    public static final String GUARDED_BYTE_ARRAY = "org.identityconnectors.common.security.GuardedByteArray";
+
+    private Constants() {
+        // private constructor for static utility class
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/DateFormatROModel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/DateFormatROModel.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/DateFormatROModel.java
new file mode 100644
index 0000000..e72b7d0
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/DateFormatROModel.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.client.console.commons;
+
+import java.util.Date;
+import org.apache.syncope.client.console.SyncopeSession;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.PropertyModel;
+
+public class DateFormatROModel implements IModel<String> {
+
+    private static final long serialVersionUID = 6677274580927636121L;
+
+    private final PropertyModel model;
+
+    public DateFormatROModel(final PropertyModel model) {
+        this.model = model;
+    }
+
+    @Override
+    public String getObject() {
+        return model.getObject() == null
+                ? ""
+                : SyncopeSession.get().getDateFormat().format((Date) model.getObject());
+    }
+
+    @Override
+    public void setObject(final String object) {
+    }
+
+    @Override
+    public void detach() {
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/HttpResourceStream.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/HttpResourceStream.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/HttpResourceStream.java
new file mode 100644
index 0000000..feeba85
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/HttpResourceStream.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.wicket.util.lang.Bytes;
+import org.apache.wicket.util.resource.AbstractResourceStream;
+import org.apache.wicket.util.resource.IFixedLocationResourceStream;
+import org.apache.wicket.util.resource.ResourceStreamNotFoundException;
+
+public class HttpResourceStream extends AbstractResourceStream implements IFixedLocationResourceStream {
+
+    private static final long serialVersionUID = 5811207817876330189L;
+
+    private transient InputStream inputStream;
+
+    private String contentType;
+
+    private String location;
+
+    private String filename;
+
+    public HttpResourceStream(final Response response) {
+        super();
+
+        Object entity = response.getEntity();
+        if (response.getStatusInfo().getStatusCode() == Response.Status.OK.getStatusCode()
+                && (entity instanceof InputStream)) {
+
+            this.inputStream = (InputStream) entity;
+            this.contentType = response.getHeaderString(HttpHeaders.CONTENT_TYPE);
+            this.location = response.getLocation() == null ? null : response.getLocation().toASCIIString();
+            String contentDisposition = response.getHeaderString(HttpHeaders.CONTENT_DISPOSITION);
+            if (StringUtils.isNotBlank(contentDisposition)) {
+                String[] splitted = contentDisposition.split("=");
+                if (splitted != null && splitted.length > 1) {
+                    this.filename = splitted[1].trim();
+                }
+            }
+        }
+    }
+
+    @Override
+    public InputStream getInputStream()
+            throws ResourceStreamNotFoundException {
+
+        return inputStream == null
+                ? new ByteArrayInputStream(new byte[0])
+                : inputStream;
+    }
+
+    @Override
+    public Bytes length() {
+        return inputStream == null
+                ? Bytes.bytes(0)
+                : null;
+    }
+
+    @Override
+    public void close() throws IOException {
+        // No need for explict closing
+    }
+
+    @Override
+    public String locationAsString() {
+        return location;
+    }
+
+    @Override
+    public String getContentType() {
+        return contentType == null
+                ? MediaType.APPLICATION_OCTET_STREAM
+                : contentType;
+    }
+
+    public String getFilename() {
+        return filename;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/JexlHelpUtil.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/JexlHelpUtil.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/JexlHelpUtil.java
new file mode 100644
index 0000000..5cfd3ce
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/JexlHelpUtil.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.link.ExternalLink;
+
+public final class JexlHelpUtil {
+
+    private static final String JEXL_SYNTAX_URL = "http://commons.apache.org/jexl/reference/syntax.html";
+
+    private JexlHelpUtil() {
+        // private constructor for static utility class
+    }
+
+    public static WebMarkupContainer getJexlHelpWebContainer(final String wicketId) {
+        final WebMarkupContainer jexlHelp = new WebMarkupContainer(wicketId);
+        jexlHelp.setVisible(false);
+        jexlHelp.setOutputMarkupPlaceholderTag(true);
+        jexlHelp.setOutputMarkupId(true);
+        jexlHelp.add(new ExternalLink("jexlLink", JEXL_SYNTAX_URL));
+        return jexlHelp;
+    }
+
+    public static AjaxLink<Void> getAjaxLink(final WebMarkupContainer wmc, final String wicketId) {
+        AjaxLink<Void> questionMarkJexlHelp = new AjaxLink<Void>(wicketId) {
+
+            private static final long serialVersionUID = -1838017408000591382L;
+
+            private boolean toogle = false;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                // using bitwise inversion as suggested by 
+                // http://pmd.sourceforge.net/pmd-4.2.5/rules/controversial.html#BooleanInversion
+                toogle ^= true;
+                wmc.setVisible(toogle);
+                target.add(wmc);
+            }
+        };
+        return questionMarkJexlHelp;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/MapChoiceRenderer.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/MapChoiceRenderer.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/MapChoiceRenderer.java
new file mode 100644
index 0000000..118db6d
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/MapChoiceRenderer.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+import java.util.Map;
+import org.apache.wicket.markup.html.form.IChoiceRenderer;
+
+public class MapChoiceRenderer<T, K> implements IChoiceRenderer<T> {
+
+    private static final long serialVersionUID = -7452881117778186644L;
+
+    private final Map<T, K> map;
+
+    public MapChoiceRenderer(final Map<T, K> map) {
+        this.map = map;
+    }
+
+    @Override
+    public Object getDisplayValue(final T key) {
+        return map.get(key);
+    }
+
+    @Override
+    public String getIdValue(final T key, final int index) {
+        return key.toString();
+    }
+}

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

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/PreferenceManager.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/PreferenceManager.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/PreferenceManager.java
new file mode 100644
index 0000000..c9b27fc
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/PreferenceManager.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.core.type.TypeReference;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.apache.wicket.request.Request;
+import org.apache.wicket.request.Response;
+import org.apache.wicket.util.cookies.CookieDefaults;
+import org.apache.wicket.util.cookies.CookieUtils;
+import org.apache.wicket.util.crypt.Base64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.StringUtils;
+
+public class PreferenceManager {
+
+    /**
+     * Logger.
+     */
+    private static final Logger LOG = LoggerFactory.getLogger(PreferenceManager.class);
+
+    private static final String PREFMAN_KEY = "prefMan";
+
+    private static final int ONE_YEAR_TIME = 60 * 60 * 24 * 365;
+
+    private static final TypeReference<Map<String, String>> MAP_TYPE_REF = new TypeReference<Map<String, String>>() {
+    };
+
+    private static final List<Integer> PAGINATOR_CHOICES = Arrays.asList(new Integer[] { 10, 25, 50 });
+
+    private final ObjectMapper mapper;
+
+    private final CookieUtils cookieUtils;
+
+    public PreferenceManager() {
+        this.mapper = new ObjectMapper();
+
+        CookieDefaults cookieDefaults = new CookieDefaults();
+        cookieDefaults.setMaxAge(ONE_YEAR_TIME);
+        this.cookieUtils = new CookieUtils(cookieDefaults);
+    }
+
+    public List<Integer> getPaginatorChoices() {
+        return PAGINATOR_CHOICES;
+    }
+
+    private Map<String, String> getPrefs(final String value) {
+        Map<String, String> prefs;
+        try {
+            if (StringUtils.hasText(value)) {
+                prefs = mapper.readValue(value, MAP_TYPE_REF);
+            } else {
+                throw new Exception("Invalid cookie value '" + value + "'");
+            }
+        } catch (Exception e) {
+            LOG.debug("No preferences found", e);
+            prefs = new HashMap<String, String>();
+        }
+
+        return prefs;
+    }
+
+    private String setPrefs(final Map<String, String> prefs) throws IOException {
+        StringWriter writer = new StringWriter();
+        mapper.writeValue(writer, prefs);
+
+        return writer.toString();
+    }
+
+    public String get(final Request request, final String key) {
+        String result = null;
+
+        String prefString = cookieUtils.load(PREFMAN_KEY);
+        if (prefString != null) {
+            final Map<String, String> prefs = getPrefs(new String(Base64.decodeBase64(prefString.getBytes())));
+            result = prefs.get(key);
+        }
+
+        return result;
+    }
+
+    public Integer getPaginatorRows(final Request request, final String key) {
+        Integer result = getPaginatorChoices().get(0);
+
+        String value = get(request, key);
+        if (value != null) {
+            result = NumberUtils.toInt(value, 10);
+        }
+
+        return result;
+    }
+
+    public List<String> getList(final Request request, final String key) {
+        final List<String> result = new ArrayList<String>();
+
+        final String compound = get(request, key);
+
+        if (StringUtils.hasText(compound)) {
+            String[] items = compound.split(";");
+            result.addAll(Arrays.asList(items));
+        }
+
+        return result;
+    }
+
+    public void set(final Request request, final Response response, final Map<String, List<String>> prefs) {
+        String prefString = cookieUtils.load(PREFMAN_KEY);
+
+        final Map<String, String> current = new HashMap<String, String>();
+        if (prefString != null) {
+            current.putAll(getPrefs(new String(Base64.decodeBase64(prefString.getBytes()))));
+        }
+
+        // after retrieved previous setting in order to overwrite the key ...
+        for (Entry<String, List<String>> entry : prefs.entrySet()) {
+            current.put(entry.getKey(), StringUtils.collectionToDelimitedString(entry.getValue(), ";"));
+        }
+
+        try {
+            cookieUtils.save(PREFMAN_KEY, new String(Base64.encodeBase64(setPrefs(current).getBytes())));
+        } catch (IOException e) {
+            LOG.error("Could not save {} info: {}", getClass().getSimpleName(), current, e);
+        }
+    }
+
+    public void set(final Request request, final Response response, final String key, final String value) {
+        String prefString = cookieUtils.load(PREFMAN_KEY);
+
+        final Map<String, String> current = new HashMap<String, String>();
+        if (prefString != null) {
+            current.putAll(getPrefs(new String(Base64.decodeBase64(prefString.getBytes()))));
+        }
+
+        // after retrieved previous setting in order to overwrite the key ...
+        current.put(key, value);
+
+        try {
+            cookieUtils.save(PREFMAN_KEY, new String(Base64.encodeBase64(setPrefs(current).getBytes())));
+        } catch (IOException e) {
+            LOG.error("Could not save {} info: {}", getClass().getSimpleName(), current, e);
+        }
+    }
+
+    public void setList(final Request request, final Response response, final String key, final List<String> values) {
+        set(request, response, key, StringUtils.collectionToDelimitedString(values, ";"));
+    }
+
+    public void setList(final Request request, final Response response, final Map<String, List<String>> prefs) {
+        set(request, response, prefs);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/PreviewUtil.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/PreviewUtil.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/PreviewUtil.java
new file mode 100644
index 0000000..98e47c0
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/PreviewUtil.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+import java.lang.reflect.InvocationTargetException;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.init.ImplementationClassNamesLoader;
+import org.apache.syncope.client.console.wicket.markup.html.form.preview.AbstractBinaryPreviewer;
+import org.apache.wicket.Component;
+import org.apache.wicket.util.crypt.Base64;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.ClassUtils;
+
+@org.springframework.stereotype.Component
+public class PreviewUtil {
+
+    @Autowired
+    private ImplementationClassNamesLoader implementationClassNamesLoader;
+
+    public Component getPreviewer(final String mimeType, final String file)
+            throws InstantiationException, IllegalAccessException, InvocationTargetException {
+
+        final Class<? extends AbstractBinaryPreviewer> previewer = StringUtils.isBlank(file)
+                ? null
+                : implementationClassNamesLoader.getPreviewerClass(mimeType);
+
+        return previewer == null
+                ? null
+                : ClassUtils.getConstructorIfAvailable(previewer, String.class, String.class, byte[].class).
+                newInstance(new Object[] { "previewer", mimeType, Base64.decodeBase64(file) }).
+                preview();
+    }
+
+    public Component getPreviewer(final String mimeType, final byte[] file)
+            throws InstantiationException, IllegalAccessException, InvocationTargetException {
+
+        final Class<? extends AbstractBinaryPreviewer> previewer =
+                implementationClassNamesLoader.getPreviewerClass(mimeType);
+
+        return previewer == null
+                ? null
+                : ClassUtils.getConstructorIfAvailable(previewer, String.class, String.class, byte[].class).
+                newInstance(new Object[] { "previewer", mimeType, file }).
+                preview();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/RoleTreeBuilder.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/RoleTreeBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/RoleTreeBuilder.java
new file mode 100644
index 0000000..c6ab6e4
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/RoleTreeBuilder.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeModel;
+import org.apache.syncope.client.console.rest.RoleRestClient;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class RoleTreeBuilder {
+
+    @Autowired
+    private RoleRestClient restClient;
+
+    private final RoleTOComparator comparator = new RoleTOComparator();
+
+    private List<RoleTO> allRoles;
+
+    private List<RoleTO> getChildRoles(final long parentRoleId, final List<RoleTO> roles) {
+        List<RoleTO> result = new ArrayList<RoleTO>();
+        for (RoleTO role : roles) {
+            if (role.getParent() == parentRoleId) {
+                result.add(role);
+            }
+        }
+
+        Collections.sort(result, comparator);
+        return result;
+    }
+
+    private void populateSubtree(final DefaultMutableTreeNode subRoot, final List<RoleTO> roles) {
+        RoleTO role = (RoleTO) subRoot.getUserObject();
+
+        DefaultMutableTreeNode child;
+        for (RoleTO subRoleTO : getChildRoles(role.getKey(), roles)) {
+            child = new DefaultMutableTreeNode(subRoleTO);
+            subRoot.add(child);
+            populateSubtree(child, roles);
+        }
+    }
+
+    public List<RoleTO> getAllRoles() {
+        return this.allRoles;
+    }
+
+    public TreeModel build() {
+        this.allRoles = this.restClient.list();
+        return build(this.allRoles);
+    }
+
+    public TreeModel build(final List<RoleTO> roles) {
+        DefaultMutableTreeNode fakeroot = new DefaultMutableTreeNode(new FakeRootRoleTO());
+
+        populateSubtree(fakeroot, roles);
+
+        return new DefaultTreeModel(fakeroot);
+    }
+
+    private static class RoleTOComparator implements Comparator<RoleTO>, Serializable {
+
+        private static final long serialVersionUID = 7085057398406518811L;
+
+        @Override
+        public int compare(final RoleTO r1, final RoleTO r2) {
+            if (r1.getKey() < r2.getKey()) {
+                return -1;
+            }
+            if (r1.getKey() == r2.getKey()) {
+                return 0;
+            }
+
+            return 1;
+        }
+    }
+
+    private static class FakeRootRoleTO extends RoleTO {
+
+        private static final long serialVersionUID = 4839183625773925488L;
+
+        public FakeRootRoleTO() {
+            super();
+
+            setKey(0);
+            setName("");
+            setParent(-1);
+        }
+
+        @Override
+        public String getDisplayName() {
+            return "";
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/RoleUtils.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/RoleUtils.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/RoleUtils.java
new file mode 100644
index 0000000..27e062b
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/RoleUtils.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+import org.apache.syncope.common.lib.to.RoleTO;
+
+public class RoleUtils {
+
+    public static RoleTO findRole(final RoleTreeBuilder roleTreeBuilder, final long roleKey) {
+        RoleTO found = null;
+        if (roleTreeBuilder.getAllRoles() != null) {
+            for (RoleTO roleTO : roleTreeBuilder.getAllRoles()) {
+                if (roleTO.getKey()== roleKey) {
+                    found = roleTO;
+                }
+            }
+        }
+        return found;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/SchemaModalPageFactory.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/SchemaModalPageFactory.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/SchemaModalPageFactory.java
new file mode 100644
index 0000000..38a60fa
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/SchemaModalPageFactory.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+import org.apache.syncope.client.console.pages.AbstractSchemaModalPage;
+import org.apache.syncope.client.console.pages.DerSchemaModalPage;
+import org.apache.syncope.client.console.pages.PlainSchemaModalPage;
+import org.apache.syncope.client.console.pages.VirSchemaModalPage;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.SchemaType;
+
+public final class SchemaModalPageFactory {
+
+    private static final long serialVersionUID = -3533177688264693505L;
+
+    private SchemaModalPageFactory() {
+        // empty constructor for static utility class
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T extends AbstractSchemaModalPage> T getSchemaModalPage(
+            final AttributableType entity, final SchemaType schemaType) {
+
+        T page;
+
+        switch (schemaType) {
+            case DERIVED:
+                page = (T) new DerSchemaModalPage(entity);
+                break;
+
+            case VIRTUAL:
+                page = (T) new VirSchemaModalPage(entity);
+                break;
+
+            default:
+                page = (T) new PlainSchemaModalPage(entity);
+                break;
+        }
+
+        return page;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/SelectChoiceRenderer.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/SelectChoiceRenderer.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/SelectChoiceRenderer.java
new file mode 100644
index 0000000..7b9164d
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/SelectChoiceRenderer.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+import org.apache.wicket.markup.html.form.IChoiceRenderer;
+
+public class SelectChoiceRenderer<T> implements IChoiceRenderer<T> {
+
+    private static final long serialVersionUID = -3242441544405909243L;
+
+    @Override
+    public Object getDisplayValue(T obj) {
+        if (obj instanceof SelectOption) {
+            return ((SelectOption) obj).getDisplayValue();
+        } else {
+            return obj.toString();
+        }
+    }
+
+    @Override
+    public String getIdValue(T obj, int i) {
+        return obj.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/SelectOption.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/SelectOption.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/SelectOption.java
new file mode 100644
index 0000000..839df70
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/SelectOption.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+import java.io.Serializable;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+
+public class SelectOption implements Serializable {
+
+    private static final long serialVersionUID = 2961127533930849828L;
+
+    private String displayValue;
+
+    private String keyValue;
+
+    public SelectOption(final String displayValue, final String keyValue) {
+        this.displayValue = displayValue;
+        this.keyValue = keyValue;
+    }
+
+    public String getDisplayValue() {
+        return displayValue;
+    }
+
+    public void setDisplayValue(final String displayValue) {
+        this.displayValue = displayValue;
+    }
+
+    public String getKeyValue() {
+        return keyValue;
+    }
+
+    public void setKeyValue(final String keyValue) {
+        this.keyValue = keyValue;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null || !(obj instanceof SelectOption)) {
+            return false;
+        }
+
+        return (keyValue == null && ((SelectOption) obj).keyValue == null) || keyValue != null
+                && keyValue.equals(((SelectOption) obj).keyValue);
+    }
+
+    @Override
+    public int hashCode() {
+        return HashCodeBuilder.reflectionHashCode(this);
+    }
+
+    @Override
+    public String toString() {
+        return keyValue;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/SortableAttributableProviderComparator.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/SortableAttributableProviderComparator.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/SortableAttributableProviderComparator.java
new file mode 100644
index 0000000..e82b9bb
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/SortableAttributableProviderComparator.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
+import org.apache.wicket.model.AbstractReadOnlyModel;
+
+public class SortableAttributableProviderComparator extends SortableDataProviderComparator<AbstractAttributableTO> {
+
+    private static final long serialVersionUID = 1775967163571699258L;
+
+    private static final Set<String> INLINE_PROPS = new HashSet<>(Arrays.asList(
+            new String[] { "key", "status", "token", "username" }));
+
+    public SortableAttributableProviderComparator(final SortableDataProvider<AbstractAttributableTO, String> provider) {
+        super(provider);
+    }
+
+    @Override
+    public int compare(final AbstractAttributableTO attributable1, AbstractAttributableTO attributable2) {
+        if (INLINE_PROPS.contains(provider.getSort().getProperty())) {
+            return super.compare(attributable1, attributable2);
+        }
+
+        return super.compare(new AttrModel(attributable1), new AttrModel(attributable2));
+    }
+
+    @SuppressWarnings("rawtypes")
+    private class AttrModel extends AbstractReadOnlyModel<Comparable> {
+
+        private static final long serialVersionUID = -7856686374020091808L;
+
+        private final Map<String, AttrTO> attrs;
+
+        private final Map<String, AttrTO> derAttrs;
+
+        private final Map<String, AttrTO> virAttrs;
+
+        public AttrModel(final AbstractAttributableTO attributableTO) {
+            super();
+
+            this.attrs = attributableTO.getPlainAttrMap();
+            this.derAttrs = attributableTO.getDerAttrMap();
+            this.virAttrs = attributableTO.getVirAttrMap();
+        }
+
+        /**
+         * @see UserAttrColumn constructor
+         */
+        @Override
+        public Comparable getObject() {
+            int hashPos = provider.getSort().getProperty().indexOf('#');
+
+            SchemaType schemaType = null;
+            final String schema;
+            if (hashPos == -1) {
+                schema = provider.getSort().getProperty();
+            } else {
+                String[] splitted = provider.getSort().getProperty().split("#");
+                try {
+                    schemaType = SchemaType.valueOf(splitted[0]);
+                } catch (IllegalArgumentException e) {
+                    // this should never happen
+                }
+                schema = provider.getSort().getProperty().substring(hashPos + 1);
+            }
+
+            final AttrTO attr;
+            if (schemaType == null) {
+                attr = this.attrs.get(schema);
+            } else {
+                switch (schemaType) {
+                    case PLAIN:
+                    default:
+                        attr = this.attrs.get(schema);
+                        break;
+
+                    case DERIVED:
+                        attr = this.derAttrs.get(schema);
+                        break;
+
+                    case VIRTUAL:
+                        attr = this.virAttrs.get(schema);
+                        break;
+                }
+            }
+
+            Comparable result = null;
+
+            List<String> values = attr == null ? null : attr.getValues();
+            if (values != null && !values.isEmpty()) {
+                result = values.iterator().next();
+            }
+
+            return result;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/SortableDataProviderComparator.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/SortableDataProviderComparator.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/SortableDataProviderComparator.java
new file mode 100644
index 0000000..bc4357d
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/SortableDataProviderComparator.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.client.console.commons;
+
+import java.io.Serializable;
+import java.util.Comparator;
+import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.PropertyModel;
+
+public class SortableDataProviderComparator<T> implements Comparator<T>, Serializable {
+
+    private static final long serialVersionUID = -8897687699977460543L;
+
+    protected final SortableDataProvider<T, String> provider;
+
+    public SortableDataProviderComparator(final SortableDataProvider<T, String> provider) {
+        this.provider = provider;
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    protected int compare(final IModel<Comparable> model1, final IModel<Comparable> model2) {
+        int result;
+
+        if (model1.getObject() == null && model2.getObject() == null) {
+            result = 0;
+        } else if (model1.getObject() == null) {
+            result = 1;
+        } else if (model2.getObject() == null) {
+            result = -1;
+        } else {
+            result = model1.getObject().compareTo(model2.getObject());
+        }
+
+        result = provider.getSort().isAscending()
+                ? result
+                : -result;
+
+        return result;
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Override
+    public int compare(final T object1, final T object2) {
+        IModel<Comparable> model1 = new PropertyModel<>(object1, provider.getSort().getProperty());
+        IModel<Comparable> model2 = new PropertyModel<>(object2, provider.getSort().getProperty());
+
+        return compare(model1, model2);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/XMLRolesReader.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/XMLRolesReader.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/XMLRolesReader.java
new file mode 100644
index 0000000..3a0b446
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/XMLRolesReader.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.client.console.commons;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * XMLRolesReader singleton class.
+ */
+public class XMLRolesReader {
+
+    /**
+     * Logger.
+     */
+    private static final Logger LOG = LoggerFactory.getLogger(XMLRolesReader.class);
+
+    private String authorizations;
+
+    private Map<Pair<String, String>, String> authMap;
+
+    public void setAuthorizations(final String authorizations) {
+        this.authorizations = authorizations;
+    }
+
+    private void init() {
+        authMap = new HashMap<Pair<String, String>, String>();
+
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        dbf.setNamespaceAware(true);
+        try {
+            DocumentBuilder db = dbf.newDocumentBuilder();
+            Document doc = db.parse(getClass().getResource("/" + authorizations).openStream());
+            doc.getDocumentElement().normalize();
+
+            Node authNode = null;
+            NodeList root = doc.getChildNodes();
+            for (int i = 0; i < root.getLength() && authNode == null; i++) {
+                if ("auth".equals(root.item(i).getNodeName())) {
+                    authNode = root.item(i);
+                }
+            }
+            if (authNode == null) {
+                throw new IllegalArgumentException("Could not find root <auth> node");
+            }
+
+            NodeList pages = authNode.getChildNodes();
+            for (int i = 0; i < pages.getLength(); i++) {
+                if ("page".equals(pages.item(i).getNodeName())) {
+                    String page = pages.item(i).getAttributes().getNamedItem("id").getTextContent();
+
+                    NodeList actions = pages.item(i).getChildNodes();
+                    for (int j = 0; j < actions.getLength(); j++) {
+                        if ("action".equals(actions.item(j).getNodeName())) {
+                            String action = actions.item(j).getAttributes().getNamedItem("id").getTextContent();
+
+                            NodeList entitlements = actions.item(j).getChildNodes();
+                            for (int k = 0; k < entitlements.getLength(); k++) {
+                                if ("entitlement".equals(entitlements.item(k).getNodeName())) {
+                                    String entitlement = entitlements.item(k).getTextContent();
+                                    authMap.put(new ImmutablePair<String, String>(page, action), entitlement);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            LOG.error("While initializing parsing of {}", authorizations, e);
+        }
+    }
+
+    /**
+     * Get entitlement required for page / action.
+     *
+     * @param pageId page
+     * @param actionId action
+     * @return entitlement required
+     */
+    public String getEntitlement(final String pageId, final String actionId) {
+        synchronized (this) {
+            if (authMap == null) {
+                init();
+            }
+        }
+
+        Pair<String, String> key = new ImmutablePair<String, String>(pageId, actionId);
+        return authMap.containsKey(key)
+                ? authMap.get(key)
+                : StringUtils.EMPTY;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/status/AbstractStatusBeanProvider.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/status/AbstractStatusBeanProvider.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/status/AbstractStatusBeanProvider.java
new file mode 100644
index 0000000..c10f55c
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/status/AbstractStatusBeanProvider.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons.status;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
+import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
+import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
+import org.apache.wicket.model.AbstractReadOnlyModel;
+import org.apache.wicket.model.IModel;
+
+public abstract class AbstractStatusBeanProvider extends SortableDataProvider<StatusBean, String> {
+
+    private static final long serialVersionUID = 4287357360778016173L;
+
+    private SortableDataProviderComparator<StatusBean> comparator;
+
+    public AbstractStatusBeanProvider(final String sort) {
+        //Default sorting
+        setSort(sort, SortOrder.ASCENDING);
+        comparator = new SortableDataProviderComparator<StatusBean>(this);
+    }
+
+    @Override
+    public Iterator<StatusBean> iterator(final long first, final long count) {
+        List<StatusBean> list = getStatusBeans();
+        Collections.sort(list, comparator);
+        return list.subList((int) first, (int) first + (int) count).iterator();
+    }
+
+    @Override
+    public long size() {
+        return getStatusBeans().size();
+    }
+
+    @Override
+    public IModel<StatusBean> model(final StatusBean resource) {
+        return new AbstractReadOnlyModel<StatusBean>() {
+
+            private static final long serialVersionUID = -7802635613997243712L;
+
+            @Override
+            public StatusBean getObject() {
+                return resource;
+            }
+        };
+    }
+
+    public abstract List<StatusBean> getStatusBeans();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/status/ConnObjectWrapper.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/status/ConnObjectWrapper.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/status/ConnObjectWrapper.java
new file mode 100644
index 0000000..be038db
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/status/ConnObjectWrapper.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons.status;
+
+import java.io.Serializable;
+import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+import org.apache.syncope.common.lib.to.ConnObjectTO;
+
+public class ConnObjectWrapper implements Serializable {
+
+    private static final long serialVersionUID = 9083721948999924299L;
+
+    private final AbstractAttributableTO attributable;
+
+    private final String resourceName;
+
+    private final ConnObjectTO connObjectTO;
+
+    public ConnObjectWrapper(final AbstractAttributableTO attributable, final String resourceName,
+            final ConnObjectTO connObjectTO) {
+
+        this.attributable = attributable;
+        this.resourceName = resourceName;
+        this.connObjectTO = connObjectTO;
+    }
+
+    public AbstractAttributableTO getAttributable() {
+        return attributable;
+    }
+
+    public String getResourceName() {
+        return resourceName;
+    }
+
+    public ConnObjectTO getConnObjectTO() {
+        return connObjectTO;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/status/Status.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/status/Status.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/status/Status.java
new file mode 100644
index 0000000..7198c2c
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/status/Status.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons.status;
+
+public enum Status {
+
+    NOT_YET_SUBMITTED(""),
+    CREATED("created"),
+    ACTIVE("active"),
+    SUSPENDED("inactive"),
+    UNDEFINED("undefined"),
+    OBJECT_NOT_FOUND("objectnotfound");
+
+    public boolean isActive() {
+        return this == ACTIVE;
+    }
+
+    private Status(final String name) {
+        this.name = name;
+    }
+
+    private final String name;
+
+    @Override
+    public String toString() {
+        return name;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusBean.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusBean.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusBean.java
new file mode 100644
index 0000000..96ddd14
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusBean.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons.status;
+
+import java.io.Serializable;
+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.AbstractAttributableTO;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.to.UserTO;
+
+public class StatusBean implements Serializable {
+
+    private static final long serialVersionUID = -5207260204921071129L;
+
+    private final Long attributableKey;
+
+    private final String attributableName;
+
+    private final String resourceName;
+
+    private String accountLink = null;
+
+    private Status status = Status.OBJECT_NOT_FOUND;
+
+    private boolean linked = true;
+
+    public StatusBean(final AbstractAttributableTO attributable, String resourceName) {
+        this.attributableKey = attributable.getKey();
+        this.attributableName = attributable instanceof UserTO
+                ? ((UserTO) attributable).getUsername() : ((RoleTO) attributable).getName();
+        this.resourceName = resourceName;
+    }
+
+    public String getAccountLink() {
+        return accountLink;
+    }
+
+    public void setAccountLink(final String accountLink) {
+        this.accountLink = accountLink;
+    }
+
+    public String getResourceName() {
+        return resourceName;
+    }
+
+    public Status getStatus() {
+        return status;
+    }
+
+    public void setStatus(final Status status) {
+        this.status = status;
+    }
+
+    public Long getAttributableId() {
+        return attributableKey;
+    }
+
+    public String getAttributableName() {
+        return attributableName;
+    }
+
+    public boolean isLinked() {
+        return linked;
+    }
+
+    public void setLinked(boolean linked) {
+        this.linked = linked;
+    }
+
+    @Override
+    public String toString() {
+        return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        return EqualsBuilder.reflectionEquals(this, obj);
+    }
+
+    @Override
+    public int hashCode() {
+        return HashCodeBuilder.reflectionHashCode(this);
+    }
+}