http://git-wip-us.apache.org/repos/asf/syncope/blob/39f8a069/client/old_console/src/main/java/org/apache/syncope/client/console/pages/AbstractSyncTaskModalPage.java
----------------------------------------------------------------------
diff --git 
a/client/old_console/src/main/java/org/apache/syncope/client/console/pages/AbstractSyncTaskModalPage.java
 
b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/AbstractSyncTaskModalPage.java
new file mode 100644
index 0000000..aa62b41
--- /dev/null
+++ 
b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/AbstractSyncTaskModalPage.java
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.pages;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.SelectChoiceRenderer;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.common.lib.to.AbstractProvisioningTaskTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.types.MatchingRule;
+import org.apache.syncope.common.lib.types.UnmatchingRule;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxLink;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+
+/**
+ * Abstract Modal window for Sync and Push Task form.
+ */
+public abstract class AbstractSyncTaskModalPage extends 
AbstractSchedTaskModalPage {
+
+    private static final long serialVersionUID = 2148403203517274669L;
+
+    protected AjaxDropDownChoicePanel<MatchingRule> matchingRule;
+
+    protected AjaxDropDownChoicePanel<UnmatchingRule> unmatchingRule;
+
+    protected abstract List<String> getSyncActions();
+
+    final IModel<List<String>> allResources = new 
LoadableDetachableModel<List<String>>() {
+
+        private static final long serialVersionUID = 5275935387613157437L;
+
+        @Override
+        protected List<String> load() {
+            final List<String> resourceNames = new ArrayList<>();
+
+            for (ResourceTO resourceTO : resourceRestClient.getAll()) {
+                resourceNames.add(resourceTO.getKey());
+            }
+
+            Collections.sort(resourceNames);
+            return resourceNames;
+        }
+    };
+
+    final IModel<List<String>> syncActionsClasses = new 
LoadableDetachableModel<List<String>>() {
+
+        private static final long serialVersionUID = 5275935387613157438L;
+
+        @Override
+        protected List<String> load() {
+            return getSyncActions();
+        }
+    };
+
+    public AbstractSyncTaskModalPage(
+            final ModalWindow window, final AbstractProvisioningTaskTO taskTO, 
final PageReference pageRef) {
+
+        super(window, taskTO, pageRef);
+
+        final AjaxDropDownChoicePanel<String> resource = new 
AjaxDropDownChoicePanel<>("resource",
+                getString("resourceName"), new PropertyModel<String>(taskTO, 
"resource"));
+        resource.setChoices(allResources.getObject());
+        resource.setChoiceRenderer(new SelectChoiceRenderer<String>());
+        resource.addRequiredLabel();
+        resource.setEnabled(taskTO.getKey() == 0);
+        resource.setStyleSheet("ui-widget-content ui-corner-all 
long_dynamicsize");
+
+        profile.add(resource);
+
+        final WebMarkupContainer syncActionsClassNames = new 
WebMarkupContainer("syncActionsClassNames");
+        syncActionsClassNames.setOutputMarkupId(true);
+        profile.add(syncActionsClassNames);
+
+        final AjaxLink<Void> first = new IndicatingAjaxLink<Void>("first") {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                taskTO.getActionsClassNames().add(StringUtils.EMPTY);
+                setVisible(false);
+                target.add(syncActionsClassNames);
+            }
+        };
+        first.setOutputMarkupPlaceholderTag(true);
+        first.setVisible(taskTO.getActionsClassNames().isEmpty());
+        syncActionsClassNames.add(first);
+
+        final ListView<String> actionsClasses = new ListView<String>(
+                "actionsClasses", new PropertyModel<List<String>>(taskTO, 
"actionsClassNames")) {
+
+                    private static final long serialVersionUID = 
9101744072914090143L;
+
+                    @Override
+                    protected void populateItem(final ListItem<String> item) {
+                        final String className = item.getModelObject();
+
+                        final DropDownChoice<String> actionsClass = new 
DropDownChoice<String>(
+                                "actionsClass", new Model<String>(className), 
syncActionsClasses.getObject());
+                        actionsClass.setNullValid(true);
+                        actionsClass.setRequired(true);
+                        actionsClass.add(new 
AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+                            private static final long serialVersionUID = 
-1107858522700306810L;
+
+                            @Override
+                            protected void onUpdate(final AjaxRequestTarget 
target) {
+                                
taskTO.getActionsClassNames().set(item.getIndex(), 
actionsClass.getModelObject());
+                                target.add(syncActionsClassNames);
+                            }
+                        });
+                        actionsClass.setRequired(true);
+                        actionsClass.setOutputMarkupId(true);
+                        actionsClass.setRequired(true);
+                        item.add(actionsClass);
+
+                        AjaxLink<Void> minus = new 
IndicatingAjaxLink<Void>("drop") {
+
+                            private static final long serialVersionUID = 
-7978723352517770644L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget 
target) {
+                                
taskTO.getActionsClassNames().remove(className);
+                                
first.setVisible(taskTO.getActionsClassNames().isEmpty());
+                                target.add(syncActionsClassNames);
+                            }
+                        };
+                        item.add(minus);
+
+                        final AjaxLink<Void> plus = new 
IndicatingAjaxLink<Void>("add") {
+
+                            private static final long serialVersionUID = 
-7978723352517770644L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget 
target) {
+                                
taskTO.getActionsClassNames().add(StringUtils.EMPTY);
+                                target.add(syncActionsClassNames);
+                            }
+                        };
+                        plus.setOutputMarkupPlaceholderTag(true);
+                        plus.setVisible(item.getIndex() == 
taskTO.getActionsClassNames().size() - 1);
+                        item.add(plus);
+                    }
+                };
+        syncActionsClassNames.add(actionsClasses);
+
+        
syncActionsClassNames.setEnabled(!syncActionsClasses.getObject().isEmpty());
+
+        final AjaxCheckBoxPanel creates = new 
AjaxCheckBoxPanel("performCreate", getString("creates"),
+                new PropertyModel<Boolean>(taskTO, "performCreate"));
+        profile.add(creates);
+
+        final AjaxCheckBoxPanel updates = new 
AjaxCheckBoxPanel("performUpdate", getString("updates"),
+                new PropertyModel<Boolean>(taskTO, "performUpdate"));
+        profile.add(updates);
+
+        final AjaxCheckBoxPanel deletes = new 
AjaxCheckBoxPanel("performDelete", getString("updates"),
+                new PropertyModel<Boolean>(taskTO, "performDelete"));
+        profile.add(deletes);
+
+        final AjaxCheckBoxPanel syncStatus = new 
AjaxCheckBoxPanel("syncStatus", getString("syncStatus"),
+                new PropertyModel<Boolean>(taskTO, "syncStatus"));
+        profile.add(syncStatus);
+
+        matchingRule = new AjaxDropDownChoicePanel<MatchingRule>(
+                "matchingRule", "matchingRule", new 
PropertyModel<MatchingRule>(taskTO, "matchingRule"));
+        matchingRule.setChoices(Arrays.asList(MatchingRule.values()));
+        ((DropDownChoice) matchingRule.getField()).setNullValid(false);
+
+        unmatchingRule = new AjaxDropDownChoicePanel<UnmatchingRule>(
+                "unmatchingRule", "unmatchingRule", new 
PropertyModel<UnmatchingRule>(taskTO, "unmatchingRule"));
+        unmatchingRule.setChoices(Arrays.asList(UnmatchingRule.values()));
+        ((DropDownChoice) unmatchingRule.getField()).setNullValid(false);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/39f8a069/client/old_console/src/main/java/org/apache/syncope/client/console/pages/ActivitiModelerPopupPage.java
----------------------------------------------------------------------
diff --git 
a/client/old_console/src/main/java/org/apache/syncope/client/console/pages/ActivitiModelerPopupPage.java
 
b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/ActivitiModelerPopupPage.java
new file mode 100644
index 0000000..05658fc
--- /dev/null
+++ 
b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/ActivitiModelerPopupPage.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.pages;
+
+import org.apache.wicket.markup.html.WebPage;
+
+public class ActivitiModelerPopupPage extends WebPage {
+
+    private static final long serialVersionUID = -7031206743629422898L;
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/39f8a069/client/old_console/src/main/java/org/apache/syncope/client/console/pages/ApprovalModalPage.java
----------------------------------------------------------------------
diff --git 
a/client/old_console/src/main/java/org/apache/syncope/client/console/pages/ApprovalModalPage.java
 
b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/ApprovalModalPage.java
new file mode 100644
index 0000000..79deeb0
--- /dev/null
+++ 
b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/ApprovalModalPage.java
@@ -0,0 +1,286 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.pages;
+
+import java.io.Serializable;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.MapChoiceRenderer;
+import org.apache.syncope.client.console.rest.ApprovalRestClient;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.DateTimeFieldPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.SpinnerFieldPanel;
+import org.apache.syncope.client.console.wicket.markup.html.list.AltListView;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.WorkflowFormPropertyTO;
+import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.wicket.Page;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import 
org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+public class ApprovalModalPage extends BaseModalPage {
+
+    private static final long serialVersionUID = -8847854414429745216L;
+
+    private final static int USER_WIN_HEIGHT = 550;
+
+    private final static int USER_WIN_WIDTH = 800;
+
+    @SpringBean
+    private ApprovalRestClient restClient;
+
+    private final ModalWindow editUserWin;
+
+    public ApprovalModalPage(final PageReference pageRef, final ModalWindow 
window, final WorkflowFormTO formTO) {
+        super();
+
+        IModel<List<WorkflowFormPropertyTO>> formProps = new 
LoadableDetachableModel<List<WorkflowFormPropertyTO>>() {
+
+            private static final long serialVersionUID = 3169142472626817508L;
+
+            @Override
+            protected List<WorkflowFormPropertyTO> load() {
+                return formTO.getProperties();
+            }
+        };
+
+        final ListView<WorkflowFormPropertyTO> propView =
+                new AltListView<WorkflowFormPropertyTO>("propView", formProps) 
{
+
+                    private static final long serialVersionUID = 
9101744072914090143L;
+
+                    @Override
+                    @SuppressWarnings({ "unchecked", "rawtypes" })
+                    protected void populateItem(final 
ListItem<WorkflowFormPropertyTO> item) {
+                        final WorkflowFormPropertyTO prop = 
item.getModelObject();
+
+                        Label label = new Label("key", prop.getName() == null
+                                        ? prop.getId()
+                                        : prop.getName());
+                        item.add(label);
+
+                        FieldPanel field;
+                        switch (prop.getType()) {
+                            case Boolean:
+                                field = new AjaxDropDownChoicePanel("value", 
label.getDefaultModelObjectAsString(),
+                                        new 
Model<Boolean>(Boolean.valueOf(prop.getValue()))).setChoices(Arrays.asList(
+                                                new String[] { "Yes", "No" }));
+                                break;
+
+                            case Date:
+                                SimpleDateFormat df = 
StringUtils.isNotBlank(prop.getDatePattern())
+                                        ? new 
SimpleDateFormat(prop.getDatePattern())
+                                        : new SimpleDateFormat();
+                                Date parsedDate = null;
+                                if (StringUtils.isNotBlank(prop.getValue())) {
+                                    try {
+                                        parsedDate = df.parse(prop.getValue());
+                                    } catch (ParseException e) {
+                                        LOG.error("Unparsable date: {}", 
prop.getValue(), e);
+                                    }
+                                }
+
+                                field = new DateTimeFieldPanel("value", 
label.getDefaultModelObjectAsString(),
+                                        new Model<Date>(parsedDate), 
df.toLocalizedPattern());
+                                break;
+
+                            case Enum:
+                                MapChoiceRenderer<String, String> enumCR =
+                                new MapChoiceRenderer<String, 
String>(prop.getEnumValues());
+
+                                field = new AjaxDropDownChoicePanel("value", 
label.getDefaultModelObjectAsString(),
+                                        new 
Model(prop.getValue())).setChoiceRenderer(enumCR).setChoices(new Model() {
+
+                                    private static final long serialVersionUID 
= -858521070366432018L;
+
+                                    @Override
+                                    public Serializable getObject() {
+                                        return new 
ArrayList<String>(prop.getEnumValues().keySet());
+                                    }
+                                });
+                                break;
+
+                            case Long:
+                                field = new SpinnerFieldPanel<Long>("value", 
label.getDefaultModelObjectAsString(),
+                                        Long.class, new 
Model<Long>(NumberUtils.toLong(prop.getValue())),
+                                        null, null);
+                                break;
+
+                            case String:
+                            default:
+                                field = new AjaxTextFieldPanel("value", 
PARENT_PATH,
+                                        new Model<String>(prop.getValue()));
+                                break;
+                        }
+
+                        field.setReadOnly(!prop.isWritable());
+                        if (prop.isRequired()) {
+                            field.addRequiredLabel();
+                        }
+
+                        item.add(field);
+                    }
+                };
+
+        final AjaxButton userDetails = new IndicatingAjaxButton("userDetails",
+                new Model<String>(getString("userDetails"))) {
+
+                    private static final long serialVersionUID = 
-4804368561204623354L;
+
+                    @Override
+                    protected void onSubmit(final AjaxRequestTarget target, 
final Form<?> form) {
+                        editUserWin.setPageCreator(new 
ModalWindow.PageCreator() {
+
+                            private static final long serialVersionUID = 
-7834632442532690940L;
+
+                            @Override
+                            public Page createPage() {
+                                return new 
ViewUserModalPage(ApprovalModalPage.this.getPageReference(), editUserWin,
+                                        
userRestClient.read(formTO.getUserKey())) {
+
+                                    private static final long serialVersionUID 
= -2819994749866481607L;
+
+                                    @Override
+                                    protected void closeAction(final 
AjaxRequestTarget target, final Form form) {
+                                        
setResponsePage(ApprovalModalPage.this);
+                                    }
+                                };
+                            }
+                        });
+
+                        editUserWin.show(target);
+                    }
+                };
+        MetaDataRoleAuthorizationStrategy.authorize(userDetails, ENABLE,
+                xmlRolesReader.getEntitlement("Users", "read"));
+
+        final AjaxButton submit = new IndicatingAjaxButton(APPLY, new 
Model<String>(getString(SUBMIT))) {
+
+            private static final long serialVersionUID = -958724007591692537L;
+
+            @Override
+            protected void onSubmit(final AjaxRequestTarget target, final 
Form<?> form) {
+
+                Map<String, WorkflowFormPropertyTO> props = 
formTO.getPropertyMap();
+
+                for (int i = 0; i < propView.size(); i++) {
+                    @SuppressWarnings("unchecked")
+                    ListItem<WorkflowFormPropertyTO> item = 
(ListItem<WorkflowFormPropertyTO>) propView.get(i);
+                    String input = ((FieldPanel) 
item.get("value")).getField().getInput();
+
+                    if (!props.containsKey(item.getModelObject().getId())) {
+                        props.put(item.getModelObject().getId(), new 
WorkflowFormPropertyTO());
+                    }
+
+                    if (item.getModelObject().isWritable()) {
+                        switch (item.getModelObject().getType()) {
+                            case Boolean:
+                                
props.get(item.getModelObject().getId()).setValue(String.valueOf("0".equals(input)));
+                                break;
+
+                            case Date:
+                            case Enum:
+                            case String:
+                            case Long:
+                            default:
+                                
props.get(item.getModelObject().getId()).setValue(input);
+                                break;
+                        }
+                    }
+                }
+
+                formTO.getProperties().clear();
+                formTO.getProperties().addAll(props.values());
+                try {
+                    restClient.submitForm(formTO);
+
+                    ((Todo) pageRef.getPage()).setModalResult(true);
+                    window.close(target);
+                } catch (SyncopeClientException e) {
+                    error(getString(Constants.ERROR) + ": " + e.getMessage());
+                    LOG.error("While submitting form {}", formTO, e);
+                    feedbackPanel.refresh(target);
+                }
+            }
+
+            @Override
+            protected void onError(final AjaxRequestTarget target, final 
Form<?> form) {
+                feedbackPanel.refresh(target);
+            }
+        };
+
+        final AjaxButton cancel = new IndicatingAjaxButton(CANCEL, new 
ResourceModel(CANCEL)) {
+
+            private static final long serialVersionUID = -958724007591692537L;
+
+            @Override
+            protected void onSubmit(final AjaxRequestTarget target, final Form 
form) {
+                window.close(target);
+            }
+
+            @Override
+            protected void onError(final AjaxRequestTarget target, final Form 
form) {
+                // nothing
+            }
+        };
+
+        cancel.setDefaultFormProcessing(false);
+
+        Form form = new Form(FORM);
+        form.add(propView);
+        form.add(userDetails);
+        form.add(submit);
+        form.add(cancel);
+
+        MetaDataRoleAuthorizationStrategy.authorize(form, ENABLE, 
xmlRolesReader.getEntitlement("Approval",
+                SUBMIT));
+
+        editUserWin = new ModalWindow("editUserWin");
+        editUserWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        editUserWin.setInitialHeight(USER_WIN_HEIGHT);
+        editUserWin.setInitialWidth(USER_WIN_WIDTH);
+        editUserWin.setCookieName("edit-user-modal");
+        add(editUserWin);
+
+        add(form);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/39f8a069/client/old_console/src/main/java/org/apache/syncope/client/console/pages/BaseModalPage.java
----------------------------------------------------------------------
diff --git 
a/client/old_console/src/main/java/org/apache/syncope/client/console/pages/BaseModalPage.java
 
b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/BaseModalPage.java
new file mode 100644
index 0000000..20892dd
--- /dev/null
+++ 
b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/BaseModalPage.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.pages;
+
+import org.apache.syncope.client.console.commons.CloseOnESCBehavior;
+
+/**
+ * Syncope Modal Window.
+ */
+public abstract class BaseModalPage extends AbstractBasePage {
+
+    private static final long serialVersionUID = -1443079028368471943L;
+
+    public BaseModalPage() {
+        super();
+
+        add(new CloseOnESCBehavior("keyup"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/39f8a069/client/old_console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
----------------------------------------------------------------------
diff --git 
a/client/old_console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
 
b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
new file mode 100644
index 0000000..2540c37
--- /dev/null
+++ 
b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.pages;
+
+import org.apache.syncope.client.console.SyncopeApplication;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.IAjaxIndicatorAware;
+import org.apache.wicket.behavior.Behavior;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+/**
+ * Syncope Wicket base-page.
+ */
+public class BasePage extends AbstractBasePage implements IAjaxIndicatorAware {
+
+    private static final long serialVersionUID = 1571997737305598502L;
+
+    public BasePage() {
+        this(null);
+    }
+
+    public BasePage(final PageParameters parameters) {
+        super(parameters);
+
+        pageSetup();
+    }
+
+    private void pageSetup() {
+        ((SyncopeApplication) getApplication()).setupNavigationPanel(this, 
xmlRolesReader, true);
+
+        final String kind = getClass().getSimpleName().toLowerCase();
+        final BookmarkablePageLink kindLink = (BookmarkablePageLink) get(kind);
+        if (kindLink != null) {
+            kindLink.add(new Behavior() {
+
+                private static final long serialVersionUID = 
1469628524240283489L;
+
+                @Override
+                public void onComponentTag(final Component component, final 
ComponentTag tag) {
+                    tag.put("class", kind);
+                }
+            });
+
+            Component kindIcon = kindLink.get(0);
+            if (kindIcon != null) {
+                kindIcon.add(new Behavior() {
+
+                    private static final long serialVersionUID = 
1469628524240283489L;
+
+                    @Override
+                    public void onComponentTag(final Component component, 
final ComponentTag tag) {
+                        tag.put("src", "../.." + SyncopeApplication.IMG_PREFIX 
+ kind + Constants.PNG_EXT);
+                    }
+                });
+            }
+        }
+
+        ((SyncopeApplication) getApplication()).setupEditProfileModal(this, 
userSelfRestClient);
+    }
+
+    @Override
+    public String getAjaxIndicatorMarkupId() {
+        return "veil";
+    }
+
+    /**
+     * Set a WindowClosedCallback for a ModalWindow instance.
+     *
+     * @param window window
+     * @param container container
+     */
+    protected void setWindowClosedCallback(final ModalWindow window, final 
WebMarkupContainer container) {
+
+        window.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() {
+
+            private static final long serialVersionUID = 8804221891699487139L;
+
+            @Override
+            public void onClose(final AjaxRequestTarget target) {
+                target.add(container);
+                if (isModalResult()) {
+                    info(getString(Constants.OPERATION_SUCCEEDED));
+                    feedbackPanel.refresh(target);
+                    setModalResult(false);
+                }
+            }
+        });
+    }
+}

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

http://git-wip-us.apache.org/repos/asf/syncope/blob/39f8a069/client/old_console/src/main/java/org/apache/syncope/client/console/pages/BulkActionModalPage.java
----------------------------------------------------------------------
diff --git 
a/client/old_console/src/main/java/org/apache/syncope/client/console/pages/BulkActionModalPage.java
 
b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/BulkActionModalPage.java
new file mode 100644
index 0000000..95e514b
--- /dev/null
+++ 
b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/BulkActionModalPage.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.pages;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.rest.BaseRestClient;
+import 
org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.common.lib.to.BulkAction;
+import org.apache.syncope.common.lib.to.BulkActionResult;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import 
org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import 
org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.ResourceModel;
+import org.springframework.beans.BeanUtils;
+
+public class BulkActionModalPage<T, S> extends BaseModalPage {
+
+    private static final long serialVersionUID = 4114026480146090962L;
+
+    public BulkActionModalPage(
+            final ModalWindow window,
+            final Collection<T> items,
+            final List<IColumn<T, S>> columns,
+            final Collection<ActionLink.ActionType> actions,
+            final BaseRestClient bulkActionExecutor,
+            final String idFieldName,
+            final String pageId) {
+
+        super();
+
+        final SortableDataProvider<T, S> dataProvider = new 
SortableDataProvider<T, S>() {
+
+            private static final long serialVersionUID = 5291903859908641954L;
+
+            @Override
+            public Iterator<? extends T> iterator(final long first, final long 
count) {
+                return items.iterator();
+            }
+
+            @Override
+            public long size() {
+                return items.size();
+            }
+
+            @Override
+            public IModel<T> model(final T object) {
+                return new CompoundPropertyModel<>(object);
+            }
+        };
+
+        add(new AjaxFallbackDefaultDataTable<>(
+                "selectedObjects",
+                new ArrayList<>(columns.subList(1, columns.size() - 1)),
+                dataProvider,
+                Integer.MAX_VALUE).setVisible(items != null && 
!items.isEmpty()));
+
+        @SuppressWarnings("rawtypes")
+        final ActionLinksPanel actionPanel = new ActionLinksPanel("actions", 
new Model(), getPageReference());
+        add(actionPanel);
+
+        for (ActionLink.ActionType action : actions) {
+            final BulkAction bulkAction = new BulkAction();
+            for (T item : items) {
+                try {
+                    bulkAction.getTargets().add(getTargetId(item, 
idFieldName).toString());
+                } catch (Exception e) {
+                    LOG.error("Error retrieving item id {}", idFieldName, e);
+                }
+            }
+
+            switch (action) {
+                case DELETE:
+                    bulkAction.setOperation(BulkAction.Type.DELETE);
+                    break;
+                case SUSPEND:
+                    bulkAction.setOperation(BulkAction.Type.SUSPEND);
+                    break;
+                case REACTIVATE:
+                    bulkAction.setOperation(BulkAction.Type.REACTIVATE);
+                    break;
+                case EXECUTE:
+                    bulkAction.setOperation(BulkAction.Type.EXECUTE);
+                    break;
+                case DRYRUN:
+                    bulkAction.setOperation(BulkAction.Type.DRYRUN);
+                    break;
+                default:
+                    LOG.error("Bulk action type not supported");
+            }
+
+            actionPanel.add(new ActionLink() {
+
+                private static final long serialVersionUID = 
-3722207913631435501L;
+
+                @Override
+                public void onClick(final AjaxRequestTarget target) {
+                    try {
+                        final BulkActionResult res = (BulkActionResult) 
bulkActionExecutor.getClass().
+                                getMethod("bulkAction", 
BulkAction.class).invoke(bulkActionExecutor, bulkAction);
+
+                        setResponsePage(new 
BulkActionResultModalPage<>(window, items, columns, res, idFieldName));
+                    } catch (Exception e) {
+                        error(getString(Constants.ERROR)
+                                + ": Operation " + bulkAction.getOperation() + 
" not supported");
+                        feedbackPanel.refresh(target);
+                    }
+
+                }
+            }, action, pageId, !items.isEmpty());
+        }
+
+        final Form<Void> form = new Form<>(FORM);
+        add(form);
+
+        final AjaxButton cancel =
+                new ClearIndicatingAjaxButton(CANCEL, new 
ResourceModel(CANCEL), getPageReference()) {
+
+                    private static final long serialVersionUID = 
-958724007591692537L;
+
+                    @Override
+                    protected void onSubmitInternal(final AjaxRequestTarget 
target, final Form<?> form) {
+                        window.close(target);
+                    }
+                };
+
+        cancel.setDefaultFormProcessing(false);
+        form.add(cancel);
+    }
+
+    private Object getTargetId(final Object target, final String idFieldName)
+            throws IllegalAccessException, InvocationTargetException {
+
+        return BeanUtils.getPropertyDescriptor(target.getClass(), idFieldName).
+                getReadMethod().invoke(target, new Object[0]);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/39f8a069/client/old_console/src/main/java/org/apache/syncope/client/console/pages/BulkActionResultModalPage.java
----------------------------------------------------------------------
diff --git 
a/client/old_console/src/main/java/org/apache/syncope/client/console/pages/BulkActionResultModalPage.java
 
b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/BulkActionResultModalPage.java
new file mode 100644
index 0000000..b9b8968
--- /dev/null
+++ 
b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/BulkActionResultModalPage.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.pages;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import 
org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionResultColumn;
+import org.apache.syncope.common.lib.to.BulkActionResult;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxLink;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import 
org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import 
org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+
+/**
+ * Show user or group status after performing a successful operation.
+ */
+public class BulkActionResultModalPage<T, S> extends BaseModalPage {
+
+    /**
+     * Serial version id.
+     */
+    private static final long serialVersionUID = 2646115294319713724L;
+
+    public BulkActionResultModalPage(
+            final ModalWindow window,
+            final Collection<T> items,
+            final List<IColumn<T, S>> columns,
+            final BulkActionResult results,
+            final String idFieldName) {
+
+        super();
+
+        final List<IColumn<T, S>> newColumnList = new 
ArrayList<>(columns.subList(1, columns.size() - 1));
+        newColumnList.add(newColumnList.size(), new ActionResultColumn<T, 
S>(results, idFieldName));
+
+        final SortableDataProvider<T, S> dataProvider = new 
SortableDataProvider<T, S>() {
+
+            private static final long serialVersionUID = 5291903859908641954L;
+
+            @Override
+            public Iterator<? extends T> iterator(final long first, final long 
count) {
+                return items.iterator();
+            }
+
+            @Override
+            public long size() {
+                return items.size();
+            }
+
+            @Override
+            public IModel<T> model(final T object) {
+                return new CompoundPropertyModel<T>(object);
+            }
+        };
+
+        add(new AjaxFallbackDefaultDataTable<T, S>(
+                "selectedObjects",
+                newColumnList,
+                dataProvider,
+                Integer.MAX_VALUE).setVisible(items != null && 
!items.isEmpty()));
+
+        final AjaxLink<Void> close = new IndicatingAjaxLink<Void>("close") {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                window.close(target);
+            }
+        };
+
+        add(close);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/39f8a069/client/old_console/src/main/java/org/apache/syncope/client/console/pages/ConfModalPage.java
----------------------------------------------------------------------
diff --git 
a/client/old_console/src/main/java/org/apache/syncope/client/console/pages/ConfModalPage.java
 
b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/ConfModalPage.java
new file mode 100644
index 0000000..0c65ac2
--- /dev/null
+++ 
b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/ConfModalPage.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.pages;
+
+import java.util.Collections;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.Mode;
+import org.apache.syncope.client.console.panels.PlainAttrsPanel;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.ConfTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import 
org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.ResourceModel;
+
+public class ConfModalPage extends BaseModalPage {
+
+    private static final long serialVersionUID = 3524777398688399977L;
+
+    public ConfModalPage(final PageReference pageRef, final ModalWindow 
window, final WebMarkupContainer parameters) {
+        super();
+
+        MetaDataRoleAuthorizationStrategy.authorize(
+                parameters, ENABLE, 
xmlRolesReader.getEntitlement("Configuration", "list"));
+        final ConfTO conf = confRestClient.list();
+
+        final Form<ConfTO> form = new Form<>("confForm");
+        form.setModel(new CompoundPropertyModel<>(conf));
+
+        form.add(new PlainAttrsPanel("paramAttrs", conf, form, Mode.ADMIN));
+
+        final AjaxButton submit = new IndicatingAjaxButton(SUBMIT, new 
ResourceModel(SUBMIT)) {
+
+            private static final long serialVersionUID = -958724007591692537L;
+
+            @Override
+            protected void onSubmit(final AjaxRequestTarget target, final 
Form<?> form) {
+                final ConfTO updatedConf = (ConfTO) form.getModelObject();
+
+                try {
+                    for (AttrTO attr : updatedConf.getPlainAttrs()) {
+                        
attr.getValues().removeAll(Collections.singleton(null));
+                        if (attr.getValues().isEmpty()
+                                || 
attr.getValues().equals(Collections.singletonList(StringUtils.EMPTY))) {
+
+                            confRestClient.delete(attr.getSchema());
+                        } else {
+                            confRestClient.set(attr);
+                        }
+                    }
+
+                    if (pageRef.getPage() instanceof BasePage) {
+                        ((BasePage) pageRef.getPage()).setModalResult(true);
+                    }
+
+                    window.close(target);
+                } catch (Exception e) {
+                    error(getString(Constants.ERROR) + ": " + e.getMessage());
+                    feedbackPanel.refresh(target);
+                }
+            }
+
+            @Override
+            protected void onError(final AjaxRequestTarget target, final 
Form<?> form) {
+                feedbackPanel.refresh(target);
+            }
+        };
+        MetaDataRoleAuthorizationStrategy.authorize(
+                submit, ENABLE, xmlRolesReader.getEntitlement("Configuration", 
"set"));
+        MetaDataRoleAuthorizationStrategy.authorize(
+                submit, ENABLE, xmlRolesReader.getEntitlement("Configuration", 
"delete"));
+        form.add(submit);
+        form.setDefaultButton(submit);
+
+        final AjaxButton cancel = new IndicatingAjaxButton(CANCEL, new 
ResourceModel(CANCEL)) {
+
+            private static final long serialVersionUID = -958724007591692537L;
+
+            @Override
+            protected void onSubmit(final AjaxRequestTarget target, final 
Form<?> form) {
+                window.close(target);
+            }
+        };
+        cancel.setDefaultFormProcessing(false);
+        form.add(cancel);
+
+        add(form);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/39f8a069/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Configuration.java
----------------------------------------------------------------------
diff --git 
a/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Configuration.java
 
b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Configuration.java
new file mode 100644
index 0000000..9f8c734
--- /dev/null
+++ 
b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Configuration.java
@@ -0,0 +1,814 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.pages;
+
+import static org.apache.syncope.client.console.pages.AbstractBasePage.LOG;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.LoggerConfig;
+import org.apache.syncope.client.console.ExtensionPanel;
+import org.apache.syncope.client.console.commons.AttrLayoutType;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.HttpResourceStream;
+import org.apache.syncope.client.console.commons.PreferenceManager;
+import 
org.apache.syncope.client.console.commons.SortableDataProviderComparator;
+import org.apache.syncope.client.console.init.ImplementationClassNamesLoader;
+import org.apache.syncope.client.console.panels.AbstractExtensionPanel;
+import org.apache.syncope.client.console.panels.JQueryUITabbedPanel;
+import org.apache.syncope.client.console.panels.LayoutsPanel;
+import org.apache.syncope.client.console.panels.PoliciesPanel;
+import org.apache.syncope.client.console.rest.LoggerRestClient;
+import org.apache.syncope.client.console.rest.NotificationRestClient;
+import org.apache.syncope.client.console.rest.SecurityQuestionRestClient;
+import org.apache.syncope.client.console.rest.WorkflowRestClient;
+import 
org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.CollectionPropertyColumn;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import 
org.apache.syncope.client.console.wicket.markup.html.link.VeilPopupSettings;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.LoggerTO;
+import org.apache.syncope.common.lib.to.NotificationTO;
+import org.apache.syncope.common.lib.to.SecurityQuestionTO;
+import org.apache.syncope.common.lib.types.LoggerLevel;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.wicket.Page;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import 
org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxLink;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import 
org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
+import 
org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
+import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
+import 
org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import 
org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
+import 
org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
+import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.image.Image;
+import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.PropertyListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.model.AbstractReadOnlyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.protocol.http.WebApplication;
+import org.apache.wicket.request.handler.resource.ResourceStreamRequestHandler;
+import org.apache.wicket.request.resource.ContentDisposition;
+import org.apache.wicket.request.resource.DynamicImageResource;
+import org.apache.wicket.request.resource.IResource;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+import org.springframework.util.ClassUtils;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+/**
+ * Configurations WebPage.
+ */
+public class Configuration extends BasePage {
+
+    private static final long serialVersionUID = -2838270869037702214L;
+
+    private static final int SYNCOPECONF_WIN_HEIGHT = 300;
+
+    private static final int SYNCOPECONF_WIN_WIDTH = 900;
+
+    private static final int NOTIFICATION_WIN_HEIGHT = 500;
+
+    private static final int NOTIFICATION_WIN_WIDTH = 1100;
+
+    private static final int SECURITY_QUESTION_WIN_HEIGHT = 300;
+
+    private static final int SECURITY_QUESTION_WIN_WIDTH = 900;
+
+    @SpringBean
+    private LoggerRestClient loggerRestClient;
+
+    @SpringBean
+    private NotificationRestClient notificationRestClient;
+
+    @SpringBean
+    private SecurityQuestionRestClient securityQuestionRestClient;
+
+    @SpringBean
+    private WorkflowRestClient wfRestClient;
+
+    @SpringBean
+    private PreferenceManager prefMan;
+
+    @SpringBean
+    private ImplementationClassNamesLoader implementationClassNamesLoader;
+
+    private final ModalWindow syncopeConfWin;
+
+    private final ModalWindow createNotificationWin;
+
+    private final ModalWindow editNotificationWin;
+
+    private final ModalWindow createSecurityQuestionWin;
+
+    private final ModalWindow editSecurityQuestionWin;
+
+    private WebMarkupContainer notificationContainer;
+
+    private WebMarkupContainer securityQuestionContainer;
+
+    private int notificationPaginatorRows;
+
+    public Configuration() {
+        super();
+
+        // Layouts
+        add(new LayoutsPanel("adminUserLayoutPanel", 
AttrLayoutType.ADMIN_USER, feedbackPanel));
+        add(new LayoutsPanel("selfUserLayoutPanel", AttrLayoutType.SELF_USER, 
feedbackPanel));
+        add(new LayoutsPanel("adminGroupLayoutPanel", 
AttrLayoutType.ADMIN_GROUP, feedbackPanel));
+        add(new LayoutsPanel("selfGroupLayoutPanel", 
AttrLayoutType.SELF_GROUP, feedbackPanel));
+        add(new LayoutsPanel("adminMembershipLayoutPanel", 
AttrLayoutType.ADMIN_MEMBERSHIP, feedbackPanel));
+        add(new LayoutsPanel("selfMembershipLayoutPanel", 
AttrLayoutType.SELF_MEMBERSHIP, feedbackPanel));
+
+        add(syncopeConfWin = new ModalWindow("syncopeConfWin"));
+        syncopeConfWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        syncopeConfWin.setInitialHeight(SYNCOPECONF_WIN_HEIGHT);
+        syncopeConfWin.setInitialWidth(SYNCOPECONF_WIN_WIDTH);
+        syncopeConfWin.setCookieName("syncopeconf-modal");
+        setupSyncopeConf();
+
+        add(new PoliciesPanel("passwordPoliciesPanel", getPageReference(), 
PolicyType.PASSWORD));
+        add(new PoliciesPanel("accountPoliciesPanel", getPageReference(), 
PolicyType.ACCOUNT));
+        add(new PoliciesPanel("syncPoliciesPanel", getPageReference(), 
PolicyType.SYNC));
+
+        add(createNotificationWin = new ModalWindow("createNotificationWin"));
+        createNotificationWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        createNotificationWin.setInitialHeight(NOTIFICATION_WIN_HEIGHT);
+        createNotificationWin.setInitialWidth(NOTIFICATION_WIN_WIDTH);
+        createNotificationWin.setCookieName("create-notification-modal");
+        add(editNotificationWin = new ModalWindow("editNotificationWin"));
+        editNotificationWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        editNotificationWin.setInitialHeight(NOTIFICATION_WIN_HEIGHT);
+        editNotificationWin.setInitialWidth(NOTIFICATION_WIN_WIDTH);
+        editNotificationWin.setCookieName("edit-notification-modal");
+        setupNotification();
+
+        add(createSecurityQuestionWin = new 
ModalWindow("createSecurityQuestionWin"));
+        createSecurityQuestionWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        
createSecurityQuestionWin.setInitialHeight(SECURITY_QUESTION_WIN_HEIGHT);
+        createSecurityQuestionWin.setInitialWidth(SECURITY_QUESTION_WIN_WIDTH);
+        
createSecurityQuestionWin.setCookieName("create-security-question-modal");
+        add(editSecurityQuestionWin = new 
ModalWindow("editSecurityQuestionWin"));
+        editSecurityQuestionWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        editSecurityQuestionWin.setInitialHeight(SECURITY_QUESTION_WIN_HEIGHT);
+        editSecurityQuestionWin.setInitialWidth(SECURITY_QUESTION_WIN_WIDTH);
+        editSecurityQuestionWin.setCookieName("edit-security-question-modal");
+        setupSecurityQuestion();
+
+        // Workflow definition stuff
+        WebMarkupContainer noActivitiEnabledForUsers = new 
WebMarkupContainer("noActivitiEnabledForUsers");
+        noActivitiEnabledForUsers.setOutputMarkupPlaceholderTag(true);
+        add(noActivitiEnabledForUsers);
+
+        WebMarkupContainer workflowDefContainer = new 
WebMarkupContainer("workflowDefContainer");
+        workflowDefContainer.setOutputMarkupPlaceholderTag(true);
+
+        if (wfRestClient.isActivitiEnabledForUsers()) {
+            noActivitiEnabledForUsers.setVisible(false);
+        } else {
+            workflowDefContainer.setVisible(false);
+        }
+
+        BookmarkablePageLink<Void> activitiModeler =
+                new BookmarkablePageLink<>("activitiModeler", 
ActivitiModelerPopupPage.class);
+        activitiModeler.setPopupSettings(new 
VeilPopupSettings().setHeight(600).setWidth(800));
+        MetaDataRoleAuthorizationStrategy.authorize(activitiModeler, ENABLE,
+                xmlRolesReader.getEntitlement("Configuration", 
"workflowDefRead"));
+        workflowDefContainer.add(activitiModeler);
+        // Check if Activiti Modeler directory is found
+        boolean activitiModelerEnabled = false;
+        try {
+            String activitiModelerDirectory = 
WebApplicationContextUtils.getWebApplicationContext(
+                    
WebApplication.get().getServletContext()).getBean("activitiModelerDirectory", 
String.class);
+            File baseDir = new File(activitiModelerDirectory);
+            activitiModelerEnabled = baseDir.exists() && baseDir.canRead() && 
baseDir.isDirectory();
+        } catch (Exception e) {
+            LOG.error("Could not check for Activiti Modeler directory", e);
+        }
+        activitiModeler.setEnabled(activitiModelerEnabled);
+
+        BookmarkablePageLink<Void> xmlEditor = new 
BookmarkablePageLink<>("xmlEditor", XMLEditorPopupPage.class);
+        xmlEditor.setPopupSettings(new 
VeilPopupSettings().setHeight(480).setWidth(800));
+        MetaDataRoleAuthorizationStrategy.authorize(xmlEditor, ENABLE,
+                xmlRolesReader.getEntitlement("Configuration", 
"workflowDefRead"));
+        workflowDefContainer.add(xmlEditor);
+
+        Image workflowDefDiagram = new Image("workflowDefDiagram", new 
Model()) {
+
+            private static final long serialVersionUID = -8457850449086490660L;
+
+            @Override
+            protected IResource getImageResource() {
+                return new DynamicImageResource() {
+
+                    private static final long serialVersionUID = 
923201517955737928L;
+
+                    @Override
+                    protected byte[] getImageData(final IResource.Attributes 
attributes) {
+                        return wfRestClient.isActivitiEnabledForUsers()
+                                ? wfRestClient.getDiagram()
+                                : new byte[0];
+                    }
+                };
+            }
+        };
+        workflowDefContainer.add(workflowDefDiagram);
+
+        MetaDataRoleAuthorizationStrategy.authorize(workflowDefContainer, 
ENABLE,
+                xmlRolesReader.getEntitlement("Configuration", 
"workflowDefRead"));
+        add(workflowDefContainer);
+
+        // Logger stuff
+        PropertyListView<LoggerTO> coreLoggerList =
+                new LoggerPropertyList(null, "corelogger", 
loggerRestClient.listLogs());
+        WebMarkupContainer coreLoggerContainer = new 
WebMarkupContainer("coreLoggerContainer");
+        coreLoggerContainer.add(coreLoggerList);
+        coreLoggerContainer.setOutputMarkupId(true);
+
+        MetaDataRoleAuthorizationStrategy.authorize(coreLoggerContainer, 
ENABLE, xmlRolesReader.getEntitlement(
+                "Configuration", "logList"));
+        add(coreLoggerContainer);
+
+        ConsoleLoggerController consoleLoggerController = new 
ConsoleLoggerController();
+        PropertyListView<LoggerTO> consoleLoggerList =
+                new LoggerPropertyList(consoleLoggerController, 
"consolelogger", consoleLoggerController.getLoggers());
+        WebMarkupContainer consoleLoggerContainer = new 
WebMarkupContainer("consoleLoggerContainer");
+        consoleLoggerContainer.add(consoleLoggerList);
+        consoleLoggerContainer.setOutputMarkupId(true);
+
+        MetaDataRoleAuthorizationStrategy.authorize(
+                consoleLoggerContainer, ENABLE, 
xmlRolesReader.getEntitlement("Configuration", "logList"));
+        add(consoleLoggerContainer);
+
+        // Extension panels
+        setupExtPanels();
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    private void setupSyncopeConf() {
+        final WebMarkupContainer parameters = new 
WebMarkupContainer("parameters");
+        parameters.setOutputMarkupId(true);
+        add(parameters);
+
+        setWindowClosedCallback(syncopeConfWin, parameters);
+
+        AjaxLink<Void> confLink = new IndicatingAjaxLink<Void>("confLink") {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                syncopeConfWin.setPageCreator(new ModalWindow.PageCreator() {
+
+                    private static final long serialVersionUID = 
-7834632442532690940L;
+
+                    @Override
+                    public Page createPage() {
+                        return new ConfModalPage(getPageReference(), 
editNotificationWin, parameters);
+                    }
+                });
+
+                syncopeConfWin.show(target);
+            }
+        };
+        parameters.add(confLink);
+
+        Link<Void> dbExportLink = new Link<Void>("dbExportLink") {
+
+            private static final long serialVersionUID = -4331619903296515985L;
+
+            @Override
+            public void onClick() {
+                try {
+                    HttpResourceStream stream = new 
HttpResourceStream(confRestClient.dbExport());
+
+                    ResourceStreamRequestHandler rsrh = new 
ResourceStreamRequestHandler(stream);
+                    rsrh.setFileName(stream.getFilename() == null ? 
"content.xml" : stream.getFilename());
+                    rsrh.setContentDisposition(ContentDisposition.ATTACHMENT);
+
+                    getRequestCycle().scheduleRequestHandlerAfterCurrent(rsrh);
+                } catch (Exception e) {
+                    error(getString(Constants.ERROR) + ": " + e.getMessage());
+                }
+            }
+        };
+        MetaDataRoleAuthorizationStrategy.authorize(
+                dbExportLink, ENABLE, 
xmlRolesReader.getEntitlement("Configuration", "export"));
+        add(dbExportLink);
+    }
+
+    private void setupNotification() {
+        notificationPaginatorRows = prefMan.getPaginatorRows(getRequest(), 
Constants.PREF_NOTIFICATION_PAGINATOR_ROWS);
+
+        final List<IColumn<NotificationTO, String>> notificationCols = new 
ArrayList<>();
+        notificationCols.add(new PropertyColumn<NotificationTO, String>(
+                new ResourceModel("key"), "key", "key"));
+        notificationCols.add(new CollectionPropertyColumn<NotificationTO>(
+                new ResourceModel("events"), "events", "events"));
+        notificationCols.add(new PropertyColumn<NotificationTO, String>(
+                new ResourceModel("subject"), "subject", "subject"));
+        notificationCols.add(new PropertyColumn<NotificationTO, String>(
+                new ResourceModel("template"), "template", "template"));
+        notificationCols.add(new PropertyColumn<NotificationTO, String>(
+                new ResourceModel("traceLevel"), "traceLevel", "traceLevel"));
+        notificationCols.add(new PropertyColumn<NotificationTO, String>(
+                new ResourceModel("active"), "active", "active"));
+
+        notificationCols.add(new AbstractColumn<NotificationTO, String>(new 
ResourceModel("actions", "")) {
+
+            private static final long serialVersionUID = 2054811145491901166L;
+
+            @Override
+            public String getCssClass() {
+                return "action";
+            }
+
+            @Override
+            public void populateItem(final 
Item<ICellPopulator<NotificationTO>> cellItem, final String componentId,
+                    final IModel<NotificationTO> model) {
+
+                final NotificationTO notificationTO = model.getObject();
+
+                final ActionLinksPanel panel = new 
ActionLinksPanel(componentId, model, getPageReference());
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = 
-3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        editNotificationWin.setPageCreator(new 
ModalWindow.PageCreator() {
+
+                            private static final long serialVersionUID = 
-7834632442532690940L;
+
+                            @Override
+                            public Page createPage() {
+                                return new 
NotificationModalPage(Configuration.this.getPageReference(),
+                                        editNotificationWin, notificationTO, 
false);
+                            }
+                        });
+
+                        editNotificationWin.show(target);
+                    }
+                }, ActionLink.ActionType.EDIT, "Notification");
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = 
-3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        try {
+                            
notificationRestClient.delete(notificationTO.getKey());
+                        } catch (SyncopeClientException e) {
+                            LOG.error("While deleting a notification", e);
+                            error(e.getMessage());
+                            return;
+                        }
+
+                        info(getString(Constants.OPERATION_SUCCEEDED));
+                        feedbackPanel.refresh(target);
+                        target.add(notificationContainer);
+                    }
+                }, ActionLink.ActionType.DELETE, "Notification");
+
+                cellItem.add(panel);
+            }
+        });
+
+        final AjaxFallbackDefaultDataTable<NotificationTO, String> 
notificationTable =
+                new AjaxFallbackDefaultDataTable<>(
+                        "notificationTable", notificationCols, new 
NotificationProvider(), notificationPaginatorRows);
+
+        notificationContainer = new 
WebMarkupContainer("notificationContainer");
+        notificationContainer.add(notificationTable);
+        notificationContainer.setOutputMarkupId(true);
+
+        add(notificationContainer);
+
+        setWindowClosedCallback(createNotificationWin, notificationContainer);
+        setWindowClosedCallback(editNotificationWin, notificationContainer);
+
+        AjaxLink<Void> createNotificationLink = new 
AjaxLink<Void>("createNotificationLink") {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                createNotificationWin.setPageCreator(new 
ModalWindow.PageCreator() {
+
+                    private static final long serialVersionUID = 
-7834632442532690940L;
+
+                    @Override
+                    public Page createPage() {
+                        return new 
NotificationModalPage(Configuration.this.getPageReference(), 
createNotificationWin,
+                                new NotificationTO(), true);
+                    }
+                });
+
+                createNotificationWin.show(target);
+            }
+        };
+
+        MetaDataRoleAuthorizationStrategy.authorize(createNotificationLink, 
ENABLE, xmlRolesReader.getEntitlement(
+                "Notification", "create"));
+        add(createNotificationLink);
+
+        @SuppressWarnings("rawtypes")
+        Form notificationPaginatorForm = new Form("notificationPaginatorForm");
+
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        final DropDownChoice rowsChooser = new DropDownChoice("rowsChooser", 
new PropertyModel(this,
+                "notificationPaginatorRows"), prefMan.getPaginatorChoices());
+
+        rowsChooser.add(new 
AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                prefMan.set(getRequest(), getResponse(), 
Constants.PREF_NOTIFICATION_PAGINATOR_ROWS, String.valueOf(
+                        notificationPaginatorRows));
+                notificationTable.setItemsPerPage(notificationPaginatorRows);
+
+                target.add(notificationContainer);
+            }
+        });
+
+        notificationPaginatorForm.add(rowsChooser);
+        add(notificationPaginatorForm);
+    }
+
+    private void setupSecurityQuestion() {
+        final List<IColumn<SecurityQuestionTO, String>> securityQuestionCols = 
new ArrayList<>();
+        securityQuestionCols.add(new PropertyColumn<SecurityQuestionTO, 
String>(
+                new ResourceModel("key"), "key", "key"));
+        securityQuestionCols.add(new PropertyColumn<SecurityQuestionTO, 
String>(
+                new ResourceModel("content"), "content", "content"));
+
+        securityQuestionCols.add(new AbstractColumn<SecurityQuestionTO, 
String>(new ResourceModel("actions", "")) {
+
+            private static final long serialVersionUID = 2054811145491901166L;
+
+            @Override
+            public String getCssClass() {
+                return "action";
+            }
+
+            @Override
+            public void populateItem(final 
Item<ICellPopulator<SecurityQuestionTO>> cellItem, final String componentId,
+                    final IModel<SecurityQuestionTO> model) {
+
+                final SecurityQuestionTO securityQuestionTO = 
model.getObject();
+
+                final ActionLinksPanel panel = new 
ActionLinksPanel(componentId, model, getPageReference());
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = 
-3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        editSecurityQuestionWin.setPageCreator(new 
ModalWindow.PageCreator() {
+
+                            private static final long serialVersionUID = 
-7834632442532690940L;
+
+                            @Override
+                            public Page createPage() {
+                                return new 
SecurityQuestionModalPage(Configuration.this.getPageReference(),
+                                        editSecurityQuestionWin, 
securityQuestionTO, false);
+                            }
+                        });
+
+                        editSecurityQuestionWin.show(target);
+                    }
+                }, ActionLink.ActionType.EDIT, "SecurityQuestion");
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = 
-3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        try {
+                            
securityQuestionRestClient.delete(securityQuestionTO.getKey());
+                        } catch (SyncopeClientException e) {
+                            LOG.error("While deleting a security question", e);
+                            error(e.getMessage());
+                            return;
+                        }
+
+                        info(getString(Constants.OPERATION_SUCCEEDED));
+                        feedbackPanel.refresh(target);
+                        target.add(securityQuestionContainer);
+                    }
+                }, ActionLink.ActionType.DELETE, "SecurityQuestion");
+
+                cellItem.add(panel);
+            }
+        });
+
+        final AjaxFallbackDefaultDataTable<SecurityQuestionTO, String> 
securityQuestionTable =
+                new AjaxFallbackDefaultDataTable<>("securityQuestionTable",
+                        securityQuestionCols, new SecurityQuestionProvider(), 
50);
+
+        securityQuestionContainer = new 
WebMarkupContainer("securityQuestionContainer");
+        securityQuestionContainer.add(securityQuestionTable);
+        securityQuestionContainer.setOutputMarkupId(true);
+
+        add(securityQuestionContainer);
+
+        setWindowClosedCallback(createSecurityQuestionWin, 
securityQuestionContainer);
+        setWindowClosedCallback(editSecurityQuestionWin, 
securityQuestionContainer);
+
+        AjaxLink<Void> createSecurityQuestionLink = new 
AjaxLink<Void>("createSecurityQuestionLink") {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+
+                createSecurityQuestionWin.setPageCreator(new 
ModalWindow.PageCreator() {
+
+                    private static final long serialVersionUID = 
-7834632442532690940L;
+
+                    @Override
+                    public Page createPage() {
+                        return new 
SecurityQuestionModalPage(Configuration.this.getPageReference(),
+                                createSecurityQuestionWin, new 
SecurityQuestionTO(), true);
+                    }
+                });
+
+                createSecurityQuestionWin.show(target);
+            }
+        };
+
+        MetaDataRoleAuthorizationStrategy.authorize(
+                createSecurityQuestionLink, ENABLE, 
xmlRolesReader.getEntitlement("SecurityQuestion", "create"));
+        add(createSecurityQuestionLink);
+    }
+
+    private void setupExtPanels() {
+        List<AbstractTab> tabs = new ArrayList<>();
+        int index = 0;
+        for (final Class<? extends AbstractExtensionPanel> clazz
+                : implementationClassNamesLoader.getExtPanelClasses()) {
+
+            String title = clazz.getAnnotation(ExtensionPanel.class) == null
+                    ? "Extension " + index
+                    : clazz.getAnnotation(ExtensionPanel.class).value();
+            tabs.add(new AbstractTab(new Model<>(title)) {
+
+                private static final long serialVersionUID = 
-5861786415855103549L;
+
+                @Override
+                public WebMarkupContainer getPanel(final String panelId) {
+                    Panel panel;
+
+                    try {
+                        panel = ClassUtils.getConstructorIfAvailable(clazz, 
String.class, PageReference.class).
+                                newInstance(panelId, 
Configuration.this.getPageReference());
+                    } catch (Exception e) {
+                        panel = new Panel(panelId) {
+
+                            private static final long serialVersionUID = 
5538299138211283825L;
+
+                        };
+
+                        LOG.error("Could not instantiate {}", clazz.getName(), 
e);
+                    }
+
+                    return panel;
+                }
+            });
+
+            index++;
+        }
+
+        JQueryUITabbedPanel<AbstractTab> extPanels = new 
JQueryUITabbedPanel<>("extPanels", tabs);
+        extPanels.setVisible(!tabs.isEmpty());
+        add(extPanels);
+    }
+
+    private class NotificationProvider extends 
SortableDataProvider<NotificationTO, String> {
+
+        private static final long serialVersionUID = -276043813563988590L;
+
+        private final SortableDataProviderComparator<NotificationTO> 
comparator;
+
+        public NotificationProvider() {
+            //Default sorting
+            setSort("key", SortOrder.ASCENDING);
+            comparator = new SortableDataProviderComparator<>(this);
+        }
+
+        @Override
+        public Iterator<NotificationTO> iterator(final long first, final long 
count) {
+            List<NotificationTO> list = 
notificationRestClient.getAllNotifications();
+
+            Collections.sort(list, comparator);
+
+            return list.subList((int) first, (int) first + (int) 
count).iterator();
+        }
+
+        @Override
+        public long size() {
+            return notificationRestClient.getAllNotifications().size();
+        }
+
+        @Override
+        public IModel<NotificationTO> model(final NotificationTO notification) 
{
+            return new AbstractReadOnlyModel<NotificationTO>() {
+
+                private static final long serialVersionUID = 
774694801558497248L;
+
+                @Override
+                public NotificationTO getObject() {
+                    return notification;
+                }
+            };
+        }
+    }
+
+    private class SecurityQuestionProvider extends 
SortableDataProvider<SecurityQuestionTO, String> {
+
+        private static final long serialVersionUID = -1458398823626281188L;
+
+        private final SortableDataProviderComparator<SecurityQuestionTO> 
comparator;
+
+        public SecurityQuestionProvider() {
+            //Default sorting
+            setSort("key", SortOrder.ASCENDING);
+            comparator = new SortableDataProviderComparator<>(this);
+        }
+
+        @Override
+        public Iterator<SecurityQuestionTO> iterator(final long first, final 
long count) {
+            List<SecurityQuestionTO> list = securityQuestionRestClient.list();
+
+            Collections.sort(list, comparator);
+
+            return list.subList((int) first, (int) first + (int) 
count).iterator();
+        }
+
+        @Override
+        public long size() {
+            return securityQuestionRestClient.list().size();
+        }
+
+        @Override
+        public IModel<SecurityQuestionTO> model(final SecurityQuestionTO 
securityQuestionTO) {
+            return new AbstractReadOnlyModel<SecurityQuestionTO>() {
+
+                private static final long serialVersionUID = 
5079291243768775704L;
+
+                @Override
+                public SecurityQuestionTO getObject() {
+                    return securityQuestionTO;
+                }
+            };
+        }
+    }
+
+    private class LoggerPropertyList extends PropertyListView<LoggerTO> {
+
+        private static final long serialVersionUID = 5911412425994616111L;
+
+        private final ConsoleLoggerController consoleLoggerController;
+
+        public LoggerPropertyList(final ConsoleLoggerController 
consoleLoggerController, final String id,
+                final List<? extends LoggerTO> list) {
+
+            super(id, list);
+            this.consoleLoggerController = consoleLoggerController;
+        }
+
+        @Override
+        protected void populateItem(final ListItem<LoggerTO> item) {
+            item.add(new Label("key"));
+
+            DropDownChoice<LoggerLevel> level = new DropDownChoice<>("level");
+            level.setModel(new IModel<LoggerLevel>() {
+
+                private static final long serialVersionUID = 
-2350428186089596562L;
+
+                @Override
+                public LoggerLevel getObject() {
+                    return item.getModelObject().getLevel();
+                }
+
+                @Override
+                public void setObject(final LoggerLevel object) {
+                    item.getModelObject().setLevel(object);
+                }
+
+                @Override
+                public void detach() {
+                }
+            });
+            level.setChoices(Arrays.asList(LoggerLevel.values()));
+            level.setOutputMarkupId(true);
+            level.add(new 
AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+                private static final long serialVersionUID = 
-1107858522700306810L;
+
+                @Override
+                protected void onUpdate(final AjaxRequestTarget target) {
+                    try {
+                        if (getId().equals("corelogger")) {
+                            
loggerRestClient.setLogLevel(item.getModelObject().getKey(),
+                                    item.getModelObject().getLevel());
+                        } else {
+                            
consoleLoggerController.setLogLevel(item.getModelObject().getKey(),
+                                    item.getModelObject().getLevel());
+                        }
+
+                        info(getString(Constants.OPERATION_SUCCEEDED));
+                    } catch (SyncopeClientException e) {
+                        info(getString(Constants.OPERATION_ERROR));
+                    }
+
+                    feedbackPanel.refresh(target);
+                }
+            });
+
+            MetaDataRoleAuthorizationStrategy.authorize(level, ENABLE, 
xmlRolesReader.getEntitlement(
+                    "Configuration", "logSetLevel"));
+
+            item.add(level);
+        }
+    }
+
+    private static class ConsoleLoggerController implements Serializable {
+
+        private static final long serialVersionUID = -1550459341476431714L;
+
+        public List<LoggerTO> getLoggers() {
+            LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+
+            List<LoggerTO> result = new ArrayList<>();
+            for (LoggerConfig logger : 
ctx.getConfiguration().getLoggers().values()) {
+                final String loggerName = 
LogManager.ROOT_LOGGER_NAME.equals(logger.getName())
+                        ? SyncopeConstants.ROOT_LOGGER : logger.getName();
+                if (logger.getLevel() != null) {
+                    LoggerTO loggerTO = new LoggerTO();
+                    loggerTO.setKey(loggerName);
+                    
loggerTO.setLevel(LoggerLevel.fromLevel(logger.getLevel()));
+                    result.add(loggerTO);
+                }
+            }
+
+            return result;
+        }
+
+        public void setLogLevel(final String name, final LoggerLevel level) {
+            LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+            LoggerConfig logConf = SyncopeConstants.ROOT_LOGGER.equals(name)
+                    ? 
ctx.getConfiguration().getLoggerConfig(LogManager.ROOT_LOGGER_NAME)
+                    : ctx.getConfiguration().getLoggerConfig(name);
+            logConf.setLevel(level.getLevel());
+            ctx.updateLoggers();
+        }
+    }
+}

Reply via email to