You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by fm...@apache.org on 2015/06/18 18:13:10 UTC

[2/4] syncope git commit: [SYNCOPE-156] provided modal content panel + features to add, edit and remove resource/conectors - still missing: 1. the possibility to edit new topology element as soon as created; 2. to show the spinner during ajax calls.

http://git-wip-us.apache.org/repos/asf/syncope/blob/a2051012/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceModal.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceModal.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceModal.java
new file mode 100644
index 0000000..8627998
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceModal.java
@@ -0,0 +1,204 @@
+/*
+ * 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.panels;
+
+import static org.apache.wicket.Component.ENABLE;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.pages.AbstractBasePage;
+import org.apache.syncope.common.lib.to.MappingItemTO;
+import org.apache.syncope.common.lib.to.ProvisionTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.Entitlement;
+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.event.Broadcast;
+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.form.Form;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.ResourceModel;
+
+/**
+ * Modal window with Resource form.
+ */
+public class ResourceModal extends ModalContent {
+
+    private static final long serialVersionUID = 1734415311027284221L;
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public ResourceModal(
+            final ModalWindow window,
+            final PageReference pageRef,
+            final ResourceTO resourceTO,
+            final boolean createFlag) {
+
+        super(window, pageRef);
+
+        final Form<ResourceTO> form = new Form<>(FORM);
+        form.setModel(new CompoundPropertyModel<>(resourceTO));
+
+        //--------------------------------
+        // Resource details panel
+        //--------------------------------
+        form.add(new ResourceDetailsPanel("details", resourceTO,
+                resourceRestClient.getPropagationActionsClasses(), createFlag));
+
+        form.add(new AnnotatedBeanPanel("systeminformation", resourceTO));
+        //--------------------------------
+
+        //--------------------------------
+        // Resource mapping panels
+        //--------------------------------
+        form.add(new ResourceMappingPanel("umapping", resourceTO, AnyTypeKind.USER));
+        form.add(new ResourceMappingPanel("gmapping", resourceTO, AnyTypeKind.GROUP));
+        //--------------------------------
+
+        //--------------------------------
+        // Resource connector configuration panel
+        //--------------------------------
+        ResourceConnConfPanel resourceConnConfPanel = new ResourceConnConfPanel("connconf", resourceTO, createFlag);
+        MetaDataRoleAuthorizationStrategy.authorize(resourceConnConfPanel, ENABLE, Entitlement.CONNECTOR_READ);
+        form.add(resourceConnConfPanel);
+        //--------------------------------
+
+        //--------------------------------
+        // Resource security panel
+        //--------------------------------
+        form.add(new ResourceSecurityPanel("security", resourceTO));
+        //--------------------------------
+
+        AjaxButton submit = new IndicatingAjaxButton(APPLY, new ResourceModel(SUBMIT, SUBMIT)) {
+
+            private static final long serialVersionUID = -958724007591692537L;
+
+            @Override
+            protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
+                final ResourceTO resourceTO = (ResourceTO) form.getDefaultModelObject();
+
+                boolean connObjectKeyError = false;
+
+                final Collection<ProvisionTO> provisions = new ArrayList<>(resourceTO.getProvisions());
+
+                for (ProvisionTO provision : provisions) {
+                    if (provision != null) {
+                        if (provision.getMapping() == null || provision.getMapping().getItems().isEmpty()) {
+                            resourceTO.getProvisions().remove(provision);
+                        } else {
+                            int uConnObjectKeyCount = CollectionUtils.countMatches(
+                                    provision.getMapping().getItems(), new Predicate<MappingItemTO>() {
+
+                                        @Override
+                                        public boolean evaluate(final MappingItemTO item) {
+                                            return item.isConnObjectKey();
+                                        }
+                                    });
+
+                            connObjectKeyError = uConnObjectKeyCount != 1;
+                        }
+                    }
+                }
+
+                if (connObjectKeyError) {
+                    error(getString("connObjectKeyValidation"));
+                    feedbackPanel.refresh(target);
+                } else {
+                    try {
+                        if (createFlag) {
+                            resourceRestClient.create(resourceTO);
+                            send(pageRef.getPage(), Broadcast.BREADTH, new ResourceCreateEvent(target, resourceTO));
+                        } else {
+                            resourceRestClient.update(resourceTO);
+                        }
+
+                        if (pageRef.getPage() instanceof AbstractBasePage) {
+                            ((AbstractBasePage) pageRef.getPage()).setModalResult(true);
+                        }
+                        window.close(target);
+                    } catch (Exception e) {
+                        LOG.error("Failure managing resource {}", resourceTO, e);
+                        error(getString(Constants.ERROR) + ": " + e.getMessage());
+                        feedbackPanel.refresh(target);
+                    }
+                }
+            }
+
+            @Override
+
+            protected void onError(final AjaxRequestTarget target, final Form<?> form) {
+                feedbackPanel.refresh(target);
+            }
+        };
+
+        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);
+            }
+
+            @Override
+            protected void onError(final AjaxRequestTarget target, final Form<?> form) {
+            }
+        };
+
+        cancel.setDefaultFormProcessing(false);
+        form.add(cancel);
+
+        add(form);
+
+        MetaDataRoleAuthorizationStrategy.authorize(
+                submit, ENABLE, createFlag ? Entitlement.RESOURCE_CREATE : Entitlement.RESOURCE_UPDATE);
+    }
+
+    public NotificationPanel getFeedbackPanel() {
+        return feedbackPanel;
+    }
+
+    public static class ResourceCreateEvent extends ModalEvent {
+
+        private final ResourceTO resourceTO;
+
+        public ResourceCreateEvent(final AjaxRequestTarget target, final ResourceTO resourceTO) {
+            super(target);
+            this.resourceTO = resourceTO;
+        }
+
+        /**
+         * Create resource getter.
+         *
+         * @return created resource.
+         */
+        public ResourceTO getResourceTO() {
+            return resourceTO;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/a2051012/client/console/src/main/java/org/apache/syncope/client/console/topology/Topology.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/topology/Topology.java b/client/console/src/main/java/org/apache/syncope/client/console/topology/Topology.java
index 0b49f12..5723859 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/topology/Topology.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/topology/Topology.java
@@ -20,25 +20,26 @@ package org.apache.syncope.client.console.topology;
 
 import static org.apache.syncope.client.console.topology.TopologyNode.Status.FAILURE;
 import static org.apache.syncope.client.console.topology.TopologyNode.Status.REACHABLE;
-import static org.apache.syncope.client.console.topology.TopologyNode.Status.UNKNOWN;
 import static org.apache.syncope.client.console.topology.TopologyNode.Status.UNREACHABLE;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
+import java.io.Serializable;
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.FutureTask;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.pages.BasePage;
+import org.apache.syncope.client.console.panels.ResourceModal.ResourceCreateEvent;
 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.ConnInstanceTO;
@@ -49,6 +50,8 @@ import org.apache.wicket.Component;
 import org.apache.wicket.ajax.AbstractAjaxTimerBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.behavior.Behavior;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 import org.apache.wicket.markup.head.IHeaderResponse;
 import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
 import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -57,6 +60,9 @@ import org.apache.wicket.markup.html.list.ListView;
 import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.LoadableDetachableModel;
 import org.apache.wicket.model.Model;
+import org.apache.wicket.protocol.ws.api.WebSocketBehavior;
+import org.apache.wicket.protocol.ws.api.WebSocketRequestHandler;
+import org.apache.wicket.protocol.ws.api.message.TextMessage;
 import org.apache.wicket.util.time.Duration;
 
 public class Topology extends BasePage {
@@ -69,6 +75,12 @@ public class Topology extends BasePage {
 
     private final int origY = 2800;
 
+    private static final int RESOURCE_MODAL_WIN_HEIGHT = 700;
+
+    private static final int RESOURCE_MODAL_WIN_WIDTH = 1000;
+
+    final ModalWindow modal;
+
     private final LoadableDetachableModel<List<ResourceTO>> resModel
             = new LoadableDetachableModel<List<ResourceTO>>() {
 
@@ -121,7 +133,74 @@ public class Topology extends BasePage {
         }
     };
 
+    private enum SupportedOperation {
+
+        CHECK_RESOURCE,
+        CHECK_CONNECTOR,
+        ADD_ENDPOINT;
+
+    }
+
     public Topology() {
+        modal = new ModalWindow("modal");
+        add(modal);
+
+        modal.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        modal.setInitialHeight(RESOURCE_MODAL_WIN_HEIGHT);
+        modal.setInitialWidth(RESOURCE_MODAL_WIN_WIDTH);
+        modal.setCookieName("resource-modal");
+
+        add(new WebSocketBehavior() {
+
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            protected void onMessage(final WebSocketRequestHandler handler, final TextMessage message) {
+                try {
+                    final ObjectMapper mapper = new ObjectMapper();
+                    final JsonNode obj = mapper.readTree(message.getText());
+
+                    switch (SupportedOperation.valueOf(obj.get("kind").asText())) {
+                        case CHECK_CONNECTOR:
+                            try {
+                                final ConnInstanceTO connector = connectorRestClient.read(obj.get("target").asLong());
+                                handler.push(String.format("{ \"status\": \"%s\", \"target\": \"%s\"}",
+                                        connectorRestClient.check(connector) ? REACHABLE : UNREACHABLE,
+                                        obj.get("target").asLong()));
+                            } catch (Exception e) {
+                                handler.push(String.format("{ \"status\": \"%s\", \"target\": \"%s\"}",
+                                        FAILURE,
+                                        obj.get("target").asLong()));
+                            }
+                            break;
+                        case CHECK_RESOURCE:
+                            try {
+                                final ResourceTO resource = resourceRestClient.read(obj.get("target").asText());
+                                handler.push(String.format("{ \"status\": \"%s\", \"target\": \"%s\"}",
+                                        connectorRestClient.check(resource) ? REACHABLE : UNREACHABLE,
+                                        obj.get("target").asText()));
+                            } catch (Exception e) {
+                                handler.push(String.format("{ \"status\": \"%s\", \"target\": \"%s\"}",
+                                        FAILURE,
+                                        obj.get("target").asText()));
+                            }
+                            break;
+                        case ADD_ENDPOINT:
+                            handler.appendJavaScript(String.format("addEndpoint('%s', '%s', '%s');",
+                                    obj.get("source").asText(),
+                                    obj.get("target").asText(),
+                                    obj.get("scope").asText()));
+                            break;
+                        default:
+                    }
+
+                } catch (IOException ex) {
+                    Logger.getLogger(Topology.class.getName()).log(Level.SEVERE, null, ex);
+                }
+
+            }
+        });
+
         // -----------------------------------------
         // Add Zoom panel
         // -----------------------------------------
@@ -148,8 +227,6 @@ public class Topology extends BasePage {
         }, ActionLink.ActionType.ZOOM_OUT, Entitlement.RESOURCE_LIST);
         // -----------------------------------------
 
-        final WebMarkupContainer jsPlace = new WebMarkupContainer("jsPlace");
-
         // -----------------------------------------
         // Add Syncope (root topologynode)
         // -----------------------------------------
@@ -161,16 +238,16 @@ public class Topology extends BasePage {
         syncopeTopologyNode.setHost(uri.getHost());
         syncopeTopologyNode.setPort(uri.getPort());
 
-        add(topologyNodePanel("syncope", syncopeTopologyNode, null, false));
+        add(topologyNodePanel("syncope", syncopeTopologyNode));
 
-        final Map<String, Map<String, TopologyNode>> connections = new HashMap<>();
-        final Map<String, TopologyNode> syncopeConnections = new HashMap<>();
-        connections.put(syncopeTopologyNode.getDisplayName(), syncopeConnections);
+        final Map<Serializable, Map<Serializable, TopologyNode>> connections = new HashMap<>();
+        final Map<Serializable, TopologyNode> syncopeConnections = new HashMap<>();
+        connections.put(syncopeTopologyNode.getKey(), syncopeConnections);
 
         // required to retrieve parent positions
         final Map<String, TopologyNode> servers = new HashMap<>();
-        final Map<String, TopologyNode> connectors = new HashMap<>();
-            // -----------------------------------------
+        final Map<Long, TopologyNode> connectors = new HashMap<>();
+        // -----------------------------------------
 
         // -----------------------------------------
         // Add Connector Servers
@@ -198,18 +275,18 @@ public class Topology extends BasePage {
                 topologynode.setX(x);
                 topologynode.setY(y);
 
-                servers.put(topologynode.getDisplayName(), topologynode);
+                servers.put(String.class.cast(topologynode.getKey()), topologynode);
 
-                item.add(topologyNodePanel("cs", topologynode, syncopeTopologyNode, false));
+                item.add(topologyNodePanel("cs", topologynode));
 
                 syncopeConnections.put(url, topologynode);
-                connections.put(url, new HashMap<String, TopologyNode>());
+                connections.put(url, new HashMap<Serializable, TopologyNode>());
             }
         };
 
         connectorServers.setOutputMarkupId(true);
         add(connectorServers);
-            // -----------------------------------------
+        // -----------------------------------------
 
         // -----------------------------------------
         // Add Connector Intances (first level)
@@ -235,12 +312,12 @@ public class Topology extends BasePage {
                         topologynode.setX(x);
                         topologynode.setY(y);
 
-                        connectors.put(topologynode.getDisplayName(), topologynode);
+                        connectors.put(Long.class.cast(topologynode.getKey()), topologynode);
 
-                        item.add(topologyNodePanel("conn", topologynode, syncopeTopologyNode, true));
+                        item.add(topologyNodePanel("conn", topologynode));
 
                         if (conn.getLocation().startsWith(CONNECTOR_SERVER_LOCATION_PREFIX)) {
-                            final Map<String, TopologyNode> remoteConnections;
+                            final Map<Serializable, TopologyNode> remoteConnections;
 
                             if (connections.containsKey(conn.getLocation())) {
                                 remoteConnections = connections.get(conn.getLocation());
@@ -248,9 +325,9 @@ public class Topology extends BasePage {
                                 remoteConnections = new HashMap<>();
                                 connections.put(conn.getLocation(), remoteConnections);
                             }
-                            remoteConnections.put(conn.getDisplayName(), topologynode);
+                            remoteConnections.put(conn.getKey(), topologynode);
                         } else {
-                            syncopeConnections.put(conn.getDisplayName(), topologynode);
+                            syncopeConnections.put(conn.getKey(), topologynode);
                         }
                     }
                 };
@@ -288,12 +365,12 @@ public class Topology extends BasePage {
                         topologynode.setX(x);
                         topologynode.setY(y);
 
-                        connectors.put(topologynode.getDisplayName(), topologynode);
+                        connectors.put(Long.class.cast(topologynode.getKey()), topologynode);
 
-                        item.add(topologyNodePanel("conn", topologynode, parent, true));
+                        item.add(topologyNodePanel("conn", topologynode));
 
                         if (conn.getLocation().startsWith(CONNECTOR_SERVER_LOCATION_PREFIX)) {
-                            final Map<String, TopologyNode> remoteConnections;
+                            final Map<Serializable, TopologyNode> remoteConnections;
 
                             if (connections.containsKey(conn.getLocation())) {
                                 remoteConnections = connections.get(conn.getLocation());
@@ -301,9 +378,9 @@ public class Topology extends BasePage {
                                 remoteConnections = new HashMap<>();
                                 connections.put(conn.getLocation(), remoteConnections);
                             }
-                            remoteConnections.put(conn.getDisplayName(), topologynode);
+                            remoteConnections.put(conn.getKey(), topologynode);
                         } else {
-                            syncopeConnections.put(conn.getDisplayName(), topologynode);
+                            syncopeConnections.put(conn.getKey(), topologynode);
                         }
                     }
                 };
@@ -315,39 +392,39 @@ public class Topology extends BasePage {
         // -----------------------------------------
         // Add Resources
         // -----------------------------------------
-        final List<String> connToBeProcessed = new ArrayList<>();
+        final List<Long> connToBeProcessed = new ArrayList<>();
         for (ResourceTO resourceTO : resModel.getObject()) {
             final TopologyNode topologynode = new TopologyNode(
                     resourceTO.getKey(), resourceTO.getKey(), TopologyNode.Kind.RESOURCE);
             topologynode.setX(origX);
             topologynode.setY(origY);
 
-            final Map<String, TopologyNode> remoteConnections;
+            final Map<Serializable, TopologyNode> remoteConnections;
 
-            if (connections.containsKey(resourceTO.getConnectorDisplayName())) {
-                remoteConnections = connections.get(resourceTO.getConnectorDisplayName());
+            if (connections.containsKey(resourceTO.getConnector())) {
+                remoteConnections = connections.get(resourceTO.getConnector());
             } else {
                 remoteConnections = new HashMap<>();
-                connections.put(resourceTO.getConnectorDisplayName(), remoteConnections);
+                connections.put(resourceTO.getConnector(), remoteConnections);
             }
 
-            remoteConnections.put(topologynode.getDisplayName(), topologynode);
+            remoteConnections.put(topologynode.getKey(), topologynode);
 
-            if (!connToBeProcessed.contains(resourceTO.getConnectorDisplayName())) {
-                connToBeProcessed.add(resourceTO.getConnectorDisplayName());
+            if (!connToBeProcessed.contains(resourceTO.getConnector())) {
+                connToBeProcessed.add(resourceTO.getConnector());
             }
         }
 
-        final ListView<String> resources = new ListView<String>("resources", connToBeProcessed) {
+        final ListView<Long> resources = new ListView<Long>("resources", connToBeProcessed) {
 
             private static final long serialVersionUID = 697862187148836038L;
 
             @Override
-            protected void populateItem(final ListItem<String> item) {
-                final String connectorDisplayName = item.getModelObject();
+            protected void populateItem(final ListItem<Long> item) {
+                final Long connectorId = item.getModelObject();
 
                 final ListView<TopologyNode> innerListView = new ListView<TopologyNode>("resources",
-                        new ArrayList<>(connections.get(connectorDisplayName).values())) {
+                        new ArrayList<>(connections.get(connectorId).values())) {
 
                             private static final long serialVersionUID = 1L;
 
@@ -356,7 +433,7 @@ public class Topology extends BasePage {
                             @Override
                             protected void populateItem(final ListItem<TopologyNode> item) {
                                 final TopologyNode topologynode = item.getModelObject();
-                                final TopologyNode parent = connectors.get(connectorDisplayName);
+                                final TopologyNode parent = connectors.get(connectorId);
 
                                 final double k;
 
@@ -377,11 +454,7 @@ public class Topology extends BasePage {
                                 topologynode.setX(x);
                                 topologynode.setY(y);
 
-                                final Panel panel = new TopologyNodePanel(
-                                        "res", topologynode, getPageReference(), resourceRestClient);
-                                panel.setMarkupId(topologynode.getDisplayName());
-                                panel.setOutputMarkupId(true);
-                                item.add(topologyNodePanel("res", topologynode, parent, true));
+                                item.add(topologyNodePanel("res", topologynode));
                             }
                         };
 
@@ -392,11 +465,15 @@ public class Topology extends BasePage {
 
         resources.setOutputMarkupId(true);
         add(resources);
-            // -----------------------------------------
+        // -----------------------------------------
 
         // -----------------------------------------
         // Create connections
         // -----------------------------------------
+        final WebMarkupContainer jsPlace = new WebMarkupContainer("jsPlace");
+        jsPlace.setOutputMarkupId(true);
+        add(jsPlace);
+
         jsPlace.add(new Behavior() {
 
             private static final long serialVersionUID = 2661717818979056044L;
@@ -414,33 +491,40 @@ public class Topology extends BasePage {
             }
         });
 
-        jsPlace.setOutputMarkupId(true);
-        add(jsPlace);
-        // -----------------------------------------
-    }
+        jsPlace.add(new AbstractAjaxTimerBehavior(Duration.seconds(2)) {
 
-    @Override
-    public String getAjaxIndicatorMarkupId() {
-        return StringUtils.EMPTY;
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            protected void onTimer(final AjaxRequestTarget target) {
+                target.appendJavaScript("checkConnection()");
+
+                if (getUpdateInterval().seconds() < 60.0) {
+                    setUpdateInterval(Duration.seconds(60));
+                }
+            }
+        });
+        // -----------------------------------------
     }
 
-    private List<String> createConnections(final Map<String, Map<String, TopologyNode>> targets) {
+    private List<String> createConnections(final Map<Serializable, Map<Serializable, TopologyNode>> targets) {
         List<String> list = new ArrayList<>();
 
-        for (Map.Entry<String, Map<String, TopologyNode>> source : targets.entrySet()) {
-            for (Map.Entry<String, TopologyNode> target : source.getValue().entrySet()) {
-                list.add(String.format("jsPlumb.connect({source:'%s',target:'%s'},def);",
+        for (Map.Entry<Serializable, Map<Serializable, TopologyNode>> source : targets.entrySet()) {
+            for (Map.Entry<Serializable, TopologyNode> target : source.getValue().entrySet()) {
+                list.add(String.format("connect('%s','%s','%s');",
                         source.getKey(),
-                        target.getKey()));
+                        target.getKey(),
+                        target.getValue().getKind()));
             }
         }
         return list;
     }
 
-    private Panel topologyNodePanel(
-            final String id, final TopologyNode node, final TopologyNode parent, final boolean active) {
-        final Panel panel = new TopologyNodePanel(id, node, getPageReference(), resourceRestClient);
-        panel.setMarkupId(node.getDisplayName());
+    private Panel topologyNodePanel(final String id, final TopologyNode node) {
+
+        final Panel panel = new TopologyNodePanel(id, node, getPageReference(), modal);
+        panel.setMarkupId(String.valueOf(node.getKey()));
         panel.setOutputMarkupId(true);
 
         panel.add(new Behavior() {
@@ -450,72 +534,32 @@ public class Topology extends BasePage {
             @Override
             public void renderHead(final Component component, final IHeaderResponse response) {
                 response.render(OnDomReadyHeaderItem.forScript(String.format("setPosition('%s', %d, %d)",
-                        node.getDisplayName(), node.getX(), node.getY())));
+                        node.getKey(), node.getX(), node.getY())));
             }
         });
 
-        final WebMarkupContainer timer = new WebMarkupContainer("timer");
-        timer.setOutputMarkupId(true);
-        panel.add(timer);
-
-        if (active) {
-            timer.add(new AbstractAjaxTimerBehavior(Duration.seconds(2)) {
-
-                private static final long serialVersionUID = 1L;
-
-                @Override
-                protected void onTimer(final AjaxRequestTarget target) {
-                    final List<TopologyReloadBehavior> behaviors = panel.getBehaviors(TopologyReloadBehavior.class);
-                    for (TopologyReloadBehavior behavior : behaviors) {
-                        panel.remove(behavior);
-                    }
-
-                    TopologyNode.Status status;
-
-                    final FutureTask<TopologyNode.Status> future = new FutureTask<>(
-                            new Callable<TopologyNode.Status>() {
-
-                                @Override
-                                public TopologyNode.Status call() throws Exception {
-                                    switch (node.getKind()) {
-                                        case CONNECTOR:
-                                            final ConnInstanceTO connector = connectorRestClient.
-                                            read(Long.class.cast(node.getKey()));
-                                            return connectorRestClient.check(connector) ? REACHABLE : UNREACHABLE;
-                                        case RESOURCE:
-                                            final ResourceTO resource = resourceRestClient.
-                                            read(String.class.cast(node.getKey()));
-                                            return connectorRestClient.check(resource) ? REACHABLE : UNREACHABLE;
-                                        default:
-                                            return UNKNOWN;
-                                    }
-                                }
-                            });
-
-                    future.run();
-
-                    try {
-                        status = future.get(10, TimeUnit.SECONDS);
-                    } catch (TimeoutException te) {
-                        LOG.warn("Check connection timed out");
-                        status = UNKNOWN;
-                    } catch (InterruptedException | ExecutionException ie) {
-                        // ignore
-                        LOG.warn("Check connection failed", ie);
-                        status = FAILURE;
-                    }
-
-                    timer.add(new TopologyReloadBehavior(parent.getDisplayName(), node.getDisplayName(), status));
-
-                    if (getUpdateInterval().seconds() < 60.0) {
-                        setUpdateInterval(Duration.seconds(60));
-                    }
+        return panel;
+    }
 
-                    target.add(timer);
-                }
-            });
+    @Override
+    public void onEvent(final IEvent<?> event) {
+        super.onEvent(event);
+
+        if (event.getPayload() instanceof ResourceCreateEvent) {
+            final ResourceCreateEvent resourceCreateEvent = ResourceCreateEvent.class.cast(event.getPayload());
+            resourceCreateEvent.getTarget().appendJavaScript(String.format(
+                    "window.Wicket.WebSocket.send('"
+                    + "{\"kind\":\"%s\",\"target\":\"%s\",\"source\":\"%s\",\"scope\":\"%s\"}"
+                    + "');",
+                    SupportedOperation.ADD_ENDPOINT,
+                    resourceCreateEvent.getResourceTO().getKey(),
+                    resourceCreateEvent.getResourceTO().getConnector(),
+                    TopologyNode.Kind.RESOURCE));
         }
+    }
 
-        return panel;
+    @Override
+    public String getAjaxIndicatorMarkupId() {
+        return StringUtils.EMPTY;
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a2051012/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyNodePanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyNodePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyNodePanel.java
index e0b9066..ab8ebc2 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyNodePanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyNodePanel.java
@@ -21,21 +21,22 @@ package org.apache.syncope.client.console.topology;
 import java.text.MessageFormat;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.pages.ResourceModalPage;
-import org.apache.syncope.client.console.rest.BaseRestClient;
+import org.apache.syncope.client.console.panels.ConnectorModal;
+import org.apache.syncope.client.console.panels.ResourceModal;
+import org.apache.syncope.client.console.rest.ConnectorRestClient;
 import org.apache.syncope.client.console.rest.ResourceRestClient;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
 import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.wicket.AttributeModifier;
-import org.apache.wicket.Page;
 import org.apache.wicket.PageReference;
 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.markup.html.basic.Label;
 import org.apache.wicket.markup.html.panel.Fragment;
 import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -45,12 +46,19 @@ public class TopologyNodePanel extends Panel {
 
     protected static final Logger LOG = LoggerFactory.getLogger(TopologyNodePanel.class);
 
-    private static final int RESOURCE_MODAL_WIN_HEIGHT = 600;
+    final ModalWindow modal;
 
-    private static final int RESOURCE_MODAL_WIN_WIDTH = 800;
+    @SpringBean
+    private ResourceRestClient resourceRestClient;
+
+    @SpringBean
+    private ConnectorRestClient connectorRestClient;
 
     public TopologyNodePanel(
-            final String id, final TopologyNode node, final PageReference pageRef, final BaseRestClient restClient) {
+            final String id,
+            final TopologyNode node,
+            final PageReference pageRef,
+            final ModalWindow modal) {
         super(id);
 
         final String resourceName = node.getDisplayName().length() > 20
@@ -64,20 +72,20 @@ public class TopologyNodePanel extends Panel {
         switch (node.getKind()) {
             case SYNCOPE:
                 title = "";
-                add(getSyncopeFragment(node, (ResourceRestClient) restClient, pageRef));
+                add(getSyncopeFragment(node, pageRef));
                 break;
             case CONNECTOR_SERVER:
                 title = node.getDisplayName();
-                add(getConnectorServerFragment(node, (ResourceRestClient) restClient, pageRef));
+                add(getConnectorServerFragment(node, pageRef));
                 break;
             case CONNECTOR:
                 title = (StringUtils.isBlank(node.getConnectionDisplayName())
                         ? "" : node.getConnectionDisplayName() + ":") + node.getDisplayName();
-                add(getConnectorFragment(node, (ResourceRestClient) restClient, pageRef));
+                add(getConnectorFragment(node, pageRef));
                 break;
             default:
                 title = node.getDisplayName().length() > 20 ? node.getDisplayName() : "";
-                add(getResurceFragment(node, (ResourceRestClient) restClient, pageRef));
+                add(getResurceFragment(node, pageRef));
         }
 
         if (StringUtils.isNotEmpty(title)) {
@@ -85,87 +93,94 @@ public class TopologyNodePanel extends Panel {
         }
 
         this.setMarkupId(node.getDisplayName());
+
+        this.modal = modal;
     }
 
-    private Fragment getSyncopeFragment(
-            final TopologyNode node, final ResourceRestClient restClient, final PageReference pageRef) {
+    private Fragment getSyncopeFragment(final TopologyNode node, final PageReference pageRef) {
         final Fragment fragment = new Fragment("actions", "syncopeActions", this);
-
-        final ModalWindow createWin = new ModalWindow("createWin");
-        fragment.add(createWin);
-
-        createWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
-        createWin.setInitialHeight(RESOURCE_MODAL_WIN_HEIGHT);
-        createWin.setInitialWidth(RESOURCE_MODAL_WIN_WIDTH);
-        createWin.setTitle(new ResourceModel("connector.new"));
-        createWin.setCookieName("connector-modal");
-
+        fragment.setOutputMarkupId(true);
         return fragment;
     }
 
-    private Fragment getConnectorServerFragment(
-            final TopologyNode node, final ResourceRestClient restClient, final PageReference pageRef) {
+    private Fragment getConnectorServerFragment(final TopologyNode node, final PageReference pageRef) {
         final Fragment fragment = new Fragment("actions", "syncopeActions", this);
-
-        final ModalWindow createWin = new ModalWindow("createWin");
-        fragment.add(createWin);
-
-        createWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
-        createWin.setInitialHeight(RESOURCE_MODAL_WIN_HEIGHT);
-        createWin.setInitialWidth(RESOURCE_MODAL_WIN_WIDTH);
-        createWin.setCookieName("connector-modal");
-        createWin.setTitle(new ResourceModel("connector.new"));
-
         return fragment;
     }
 
-    private Fragment getConnectorFragment(
-            final TopologyNode node, final ResourceRestClient restClient, final PageReference pageRef) {
+    private Fragment getConnectorFragment(final TopologyNode node, final PageReference pageRef) {
         final Fragment fragment = new Fragment("actions", "connectorWithNoResourceActions", this);
+        fragment.setOutputMarkupId(true);
 
-        final ModalWindow createWin = new ModalWindow("createWin");
-        fragment.add(createWin);
+        final AjaxLink<String> delete = new ClearIndicatingAjaxLink<String>("delete", pageRef) {
 
-        createWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
-        createWin.setInitialHeight(RESOURCE_MODAL_WIN_HEIGHT);
-        createWin.setInitialWidth(RESOURCE_MODAL_WIN_WIDTH);
-        createWin.setCookieName("resource-modal");
-        createWin.setTitle(new ResourceModel("resource.new"));
+            private static final long serialVersionUID = 3776750333491622263L;
 
-        final ModalWindow editWin = new ModalWindow("editWin");
-        fragment.add(editWin);
+            @Override
+            public void onClickInternal(final AjaxRequestTarget target) {
+                try {
+                    connectorRestClient.delete(Long.class.cast(node.getKey()));
+                    target.appendJavaScript(String.format("jsPlumb.remove('%s');", node.getKey()));
+                    info(getString(Constants.OPERATION_SUCCEEDED));
+                } catch (SyncopeClientException e) {
+                    error(getString(Constants.ERROR) + ": " + e.getMessage());
+                    LOG.error("While deleting resource {}", node.getKey(), e);
+                }
+            }
+        };
+        fragment.add(delete);
 
-        editWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
-        editWin.setInitialHeight(RESOURCE_MODAL_WIN_HEIGHT);
-        editWin.setInitialWidth(RESOURCE_MODAL_WIN_WIDTH);
-        editWin.setCookieName("connector-modal");
-        editWin.setTitle(MessageFormat.format(getString("connector.edit"), node.getKey()));
+        final AjaxLink<String> create = new ClearIndicatingAjaxLink<String>("create", pageRef) {
+
+            private static final long serialVersionUID = 3776750333491622263L;
+
+            @Override
+            public void onClickInternal(final AjaxRequestTarget target) {
+                final ResourceTO resourceTO = new ResourceTO();
+                resourceTO.setConnector(Long.class.cast(node.getKey()));
+                resourceTO.setConnectorDisplayName(node.getDisplayName());
+
+                modal.setContent(new ResourceModal(modal, pageRef, resourceTO, true));
+
+                modal.setTitle(getString("resource.new"));
+                modal.show(target);
+            }
+        };
+        fragment.add(create);
+
+        final AjaxLink<String> edit = new ClearIndicatingAjaxLink<String>("edit", pageRef) {
+
+            private static final long serialVersionUID = 3776750333491622263L;
+
+            @Override
+            public void onClickInternal(final AjaxRequestTarget target) {
+
+                modal.setContent(new ConnectorModal(
+                        modal,
+                        pageRef,
+                        connectorRestClient.read(Long.class.cast(node.getKey()))));
+
+                modal.setTitle(MessageFormat.format(getString("connector.edit"), node.getKey()));
+                modal.show(target);
+            }
+        };
+        fragment.add(edit);
 
         return fragment;
     }
 
-    private Fragment getResurceFragment(
-            final TopologyNode node, final ResourceRestClient restClient, final PageReference pageRef) {
+    private Fragment getResurceFragment(final TopologyNode node, final PageReference pageRef) {
         final Fragment fragment = new Fragment("actions", "resourceActions", this);
 
-        final ModalWindow editWin = new ModalWindow("editWin");
-        fragment.add(editWin);
-
-        editWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
-        editWin.setInitialHeight(RESOURCE_MODAL_WIN_HEIGHT);
-        editWin.setInitialWidth(RESOURCE_MODAL_WIN_WIDTH);
-        editWin.setCookieName("resource-modal");
-        editWin.setTitle(MessageFormat.format(getString("resource.edit"), node.getKey()));
-
-        final AjaxLink<String> delete = new IndicatingAjaxLink<String>("delete") {
+        final AjaxLink<String> delete = new ClearIndicatingAjaxLink<String>("delete", pageRef) {
 
             private static final long serialVersionUID = 3776750333491622263L;
 
             @Override
-            public void onClick(final AjaxRequestTarget target) {
+            public void onClickInternal(final AjaxRequestTarget target) {
                 try {
-                    restClient.delete(node.getKey().toString());
-                    target.appendJavaScript(String.format("jsPlumb.remove('%s');", node.getDisplayName()));
+                    resourceRestClient.delete(node.getKey().toString());
+                    target.appendJavaScript(String.format("jsPlumb.remove('%s');", node.getKey()));
                     info(getString(Constants.OPERATION_SUCCEEDED));
                 } catch (SyncopeClientException e) {
                     error(getString(Constants.ERROR) + ": " + e.getMessage());
@@ -175,27 +190,21 @@ public class TopologyNodePanel extends Panel {
         };
         fragment.add(delete);
 
-        final AjaxLink<String> edit = new IndicatingAjaxLink<String>("edit") {
+        final AjaxLink<String> edit = new ClearIndicatingAjaxLink<String>("edit", pageRef) {
 
             private static final long serialVersionUID = 3776750333491622263L;
 
             @Override
-            public void onClick(final AjaxRequestTarget target) {
-                editWin.setPageCreator(new ModalWindow.PageCreator() {
-
-                    private static final long serialVersionUID = -7834632442532690940L;
-
-                    @Override
-                    public Page createPage() {
-                        return new ResourceModalPage(
-                                pageRef,
-                                editWin,
-                                restClient.read(node.getKey().toString()),
-                                false);
-                    }
-                });
-
-                editWin.show(target);
+            public void onClickInternal(final AjaxRequestTarget target) {
+
+                modal.setContent(new ResourceModal(
+                        modal,
+                        pageRef,
+                        resourceRestClient.read(node.getKey().toString()),
+                        false));
+
+                modal.setTitle(MessageFormat.format(getString("resource.edit"), node.getKey()));
+                modal.show(target);
             }
         };
         fragment.add(edit);

http://git-wip-us.apache.org/repos/asf/syncope/blob/a2051012/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyReloadBehavior.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyReloadBehavior.java b/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyReloadBehavior.java
deleted file mode 100644
index 434c7ea..0000000
--- a/client/console/src/main/java/org/apache/syncope/client/console/topology/TopologyReloadBehavior.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.client.console.topology;
-
-import org.apache.wicket.Component;
-import org.apache.wicket.behavior.Behavior;
-import org.apache.wicket.markup.head.IHeaderResponse;
-import org.apache.wicket.markup.head.OnLoadHeaderItem;
-
-public class TopologyReloadBehavior extends Behavior {
-
-    private static final long serialVersionUID = 1L;
-
-    private final String source;
-
-    private final String target;
-
-    private final TopologyNode.Status status;
-
-    public TopologyReloadBehavior(final String source, final String target, final TopologyNode.Status status) {
-        this.source = source;
-        this.target = target;
-        this.status = status;
-    }
-
-    @Override
-    public void renderHead(final Component component, final IHeaderResponse response) {
-
-        switch (status) {
-            case UNKNOWN:
-                response.render(OnLoadHeaderItem.forScript(String.format("unknown('%s', '%s')", source, target)));
-                break;
-            case REACHABLE:
-                response.render(OnLoadHeaderItem.forScript(String.format("enable('%s', '%s')", source, target)));
-                break;
-            case UNREACHABLE:
-                response.render(OnLoadHeaderItem.forScript(String.format("disable('%s', '%s')", source, target)));
-                break;
-            default:
-                response.render(OnLoadHeaderItem.forScript(String.format("failure('%s', '%s')", source, target)));
-            // remove subtree
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/a2051012/client/console/src/main/resources/META-INF/resources/css/topology.css
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/META-INF/resources/css/topology.css b/client/console/src/main/resources/META-INF/resources/css/topology.css
index c5744cb..be3f04d 100644
--- a/client/console/src/main/resources/META-INF/resources/css/topology.css
+++ b/client/console/src/main/resources/META-INF/resources/css/topology.css
@@ -60,12 +60,6 @@
     filter:alpha(opacity=60);
 }
 
-.active {
-    border:1px dotted green;
-}
-.hover {
-    border:1px dotted red;
-}
 ._jsPlumb_dragging { 
     z-index:4000;
 }
@@ -116,6 +110,7 @@ div#drawing {
 div#zoom {
     padding : 10px;
     text-align: right;
+    width: 100%;
 }
 
 div#zoom .fa{

http://git-wip-us.apache.org/repos/asf/syncope/blob/a2051012/client/console/src/main/resources/META-INF/resources/js/topology.js
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/META-INF/resources/js/topology.js b/client/console/src/main/resources/META-INF/resources/js/topology.js
index 5592b9c..f2a7ac3 100644
--- a/client/console/src/main/resources/META-INF/resources/js/topology.js
+++ b/client/console/src/main/resources/META-INF/resources/js/topology.js
@@ -47,15 +47,8 @@ var failedConnectorStyle = {
     outlineWidth: 1
 };
 
-var disabledConnectorStyle = {
-    lineWidth: 2,
-    strokeStyle: "rgba(255, 69, 0, 1)",
-    outlineColor: "#666",
-    outlineWidth: 1
-};
-
-var disabledConnectorHoverStyle = {
-    strokeStyle: "#FF8C00" 
+var failedConnectorHoverStyle = {
+    strokeStyle: "#FFFFFF" 
 };
 
 var failedEndpointStyle = {
@@ -69,6 +62,17 @@ var failedEndpointStyle = {
     radius: 3.5
 };
 
+var disabledConnectorStyle = {
+    lineWidth: 2,
+    strokeStyle: "rgba(255, 69, 0, 1)",
+    outlineColor: "#666",
+    outlineWidth: 1
+};
+
+var disabledConnectorHoverStyle = {
+    strokeStyle: "#FF8C00" 
+};
+
 var disabledEndpointStyle = {
     gradient: {
 	stops: [
@@ -102,22 +106,22 @@ var enabledEndpointStyle = {
     radius: 3.5
 };
 
-function disable(sourceName, targetName){
-    jsPlumb.select({target:targetName}).setPaintStyle(disabledConnectorStyle).setHoverPaintStyle({strokeStyle: "#FF8C00" });
+window.disable = function(targetName){
+    jsPlumb.select({target:targetName}).setPaintStyle(disabledConnectorStyle).setHoverPaintStyle(disabledConnectorHoverStyle);
     jsPlumb.selectEndpoints({element: [targetName]}).setPaintStyle(disabledEndpointStyle);
 }
 
-function enable(sourceName, targetName){
-    jsPlumb.select({target:targetName}).setPaintStyle(enabledConnectorStyle).setHoverPaintStyle({strokeStyle: "#00FF00" });
+window.enable = function(targetName){
+    jsPlumb.select({target:targetName}).setPaintStyle(enabledConnectorStyle).setHoverPaintStyle(enabledConnectorHoverStyle);
     jsPlumb.selectEndpoints({element: [targetName]}).setPaintStyle(enabledEndpointStyle);
 }
 
-function failure(sourceName, targetName){
-    jsPlumb.select({target:targetName}).setPaintStyle(failedConnectorStyle).setHoverPaintStyle({strokeStyle: "#FFFFFF" });
+window.failure = function(targetName){
+    jsPlumb.select({target:targetName}).setPaintStyle(failedConnectorStyle).setHoverPaintStyle(failedConnectorHoverStyle);
     jsPlumb.selectEndpoints({element: [targetName]}).setPaintStyle(failedEndpointStyle);
 }
 
-function unknown(sourceName, targetName){
+window.unknown = function(targetName){
 }
 
 function getTopology(){
@@ -216,6 +220,12 @@ window.zoomOut = function(el, instance, transformOrigin) {
     $.cookie("topology", JSON.stringify(val), { expires: 9999 });
 };
 
+window.connect = function(source, target, scope){
+    if(jsPlumb.select({source:source, target:target, scope: scope}) !=null){
+	jsPlumb.connect({source:source, target:target, scope: scope}, def);
+    }
+}
+
 window.activate = function(zoom){
     jsPlumb.draggable(jsPlumb.getSelector(".window"));
     jsPlumb.setContainer("drawing");
@@ -228,11 +238,46 @@ window.activate = function(zoom){
     var val = getTopology();
     if(val.__zoom__ == null){
 	setZoom($("#drawing")[0], zoom);
-    }else{
+    } else {
 	setZoom($("#drawing")[0], val.__zoom__);
     }
 }
 
+window.checkConnection = function() {
+    jsPlumb.select({scope:"CONNECTOR"}).each(function(connection) {
+        Wicket.WebSocket.send("{ \"kind\":\"CHECK_CONNECTOR\", \"target\":\"" + connection.target.id + "\" }");
+    });
+    jsPlumb.select({scope:"RESOURCE"}).each(function(connection) {
+        Wicket.WebSocket.send("{ \"kind\":\"CHECK_RESOURCE\", \"target\":\"" + connection.target.id + "\" }");
+    });
+}
+
+window.addEndpoint = function(source, target, scope) {
+    var sourceElement = $('#' + source);
+    var element = sourceElement.clone();
+    element.attr('id', target);
+    element.removeAttr('data-original-title');
+    
+    var top = parseFloat(sourceElement.css("top")) + 10;
+    var left = parseFloat(sourceElement.css("left")) - 150;
+
+    if(scope == 'RESOURCE'){
+	var style = 'topology_res';
+    }else{
+	var style = 'topology_conn';
+    }
+    
+    element.attr('class', 'window jsplumb-draggable _jsPlumb_endpoint_anchor_ ' + style);
+    
+    element.find('p').text(target);
+    
+    $('#drawing').append(element);
+    setPosition(target, left, top);
+    
+    jsPlumb.draggable(element);
+    jsPlumb.connect({ source:source, target:target, scope:scope }, def);
+}
+
 jsPlumb.importDefaults({
     Connector : [ "Straight" ],
     DragOptions: {
@@ -242,3 +287,25 @@ jsPlumb.importDefaults({
     HoverClass: "connector-hover"
 });
 
+jQuery(function($) {
+    Wicket.Event.subscribe("/websocket/message", function(jqEvent, message) {
+	var val = JSON.parse(decodeURIComponent(message));
+	switch (val.status) {
+	case 'UNKNOWN':
+	    unknown(val.target);
+	    break;
+        case 'REACHABLE':
+	    enable(val.target);
+	    break;
+	case 'UNREACHABLE':
+	    disable(val.target);
+	    break;
+        case 'FAILURE':
+	    failure(val.target);
+	    break;
+	default:
+	    break;
+	}
+    });
+});
+

http://git-wip-us.apache.org/repos/asf/syncope/blob/a2051012/client/console/src/main/resources/META-INF/web-fragment.xml
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/META-INF/web-fragment.xml b/client/console/src/main/resources/META-INF/web-fragment.xml
index f19df05..04cd14e 100644
--- a/client/console/src/main/resources/META-INF/web-fragment.xml
+++ b/client/console/src/main/resources/META-INF/web-fragment.xml
@@ -44,7 +44,7 @@ under the License.
     
   <filter>
     <filter-name>SyncopeConsole</filter-name>
-    <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
+    <filter-class>org.apache.wicket.protocol.ws.javax.JavaxWebSocketFilter</filter-class>
     <init-param>
       <param-name>filterMappingUrlPattern</param-name>
       <param-value>/*</param-value>

http://git-wip-us.apache.org/repos/asf/syncope/blob/a2051012/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html b/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
index 147f819..b01e9d9 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
@@ -39,7 +39,7 @@ under the License.
     <script type="text/javascript" src="webjars/bootstrap/${bootstrap.version}/js/bootstrap.min.js"></script>
     <script type="text/javascript" src="webjars/bootstrap-select/${bootstrap-select.version}/dist/js/bootstrap-select.min.js"></script>
     <script type="text/javascript" src="js/AdminLTE-app.min.js"></script>
-    
+
     <script type="text/javascript">
       var notificationShownTimes = 0;
       function showNotification(componentId, messagecount) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/a2051012/client/console/src/main/resources/org/apache/syncope/client/console/pages/ConnectorModalPage.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/pages/ConnectorModalPage.html b/client/console/src/main/resources/org/apache/syncope/client/console/pages/ConnectorModalPage.html
deleted file mode 100644
index b85acb6..0000000
--- a/client/console/src/main/resources/org/apache/syncope/client/console/pages/ConnectorModalPage.html
+++ /dev/null
@@ -1,161 +0,0 @@
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License.  You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied.  See the License for the
-specific language governing permissions and limitations
-under the License.
--->
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
-  <wicket:extend>
-    <p class="ui-widget ui-corner-all ui-widget-header">
-        <span wicket:id="new"/>&nbsp;<wicket:message key="title"/>&nbsp;<span wicket:id="key"/>
-    </p>
-    <div style="margin: 5px;">
-      <form wicket:id="form">
-        <div id="tabs">
-          <ul>
-            <li class="tabs-selected"><a href="#tabs-1"><span><wicket:message key="tab1"/></span></a></li>
-            <li><a href="#tabs-2"><span><wicket:message key="tab2"/></span></a></li>
-            <li><a href="#tabs-3"><span><wicket:message key="tab3"/></span></a></li>
-          </ul>
-          <div id="tabs-1">
-            <div id="formtable">
-              <div class="tablerow alt">
-                <div class="tablecolumn_label short_dynamicsize">
-                  <label for="displayName"><wicket:message key="displayName"/></label>
-                </div>
-                <div class="tablecolumn_field short_dynamicsize">
-                  <span wicket:id="displayName">[displayName]</span>
-                </div>
-              </div>
-
-              <div class="tablerow">
-                <div class="tablecolumn_label short_dynamicsize">
-                  <label for="location"><wicket:message key="location"/></label>
-                </div>
-                <div class="tablecolumn_field short_dynamicsize">
-                  <span wicket:id="location">[location]</span>
-                </div>
-              </div>
-
-              <div class="tablerow alt">
-                <div class="tablecolumn_label short_dynamicsize">
-                  <label for="name"><wicket:message key="name"/></label>
-                </div>
-                <div class="tablecolumn_field medium_dynamicsize">
-                  <span wicket:id="connectorName">[connectorName]</span>
-                </div>
-              </div>
-
-              <div class="tablerow">
-                <div class="tablecolumn_label short_dynamicsize">
-                  <label for="version"><wicket:message key="version"/></label>
-                </div>
-                <div class="tablecolumn_field short_dynamicsize">
-                  <span wicket:id="version">[version]</span>
-                </div>
-              </div>
-            </div>
-            <div style="display: table; border: 1px solid #BBBBBB;">
-              <div class="tablerow2 alt">
-                <div class="tablecolumn2_label short_dynamicsize">
-                  <label for="connRequestTimeout"><wicket:message key="connRequestTimeout"/></label>
-                </div>
-                <div class="tablecolumn2_field short_dynamicsize">
-                  <span wicket:id="connRequestTimeout">[connRequestTimeout]</span>
-                </div>
-                <div class="tablecolumn2_label short_dynamicsize">
-                  <label for="poolMaxObjects"><wicket:message key="poolMaxObjects"/></label>
-                </div>
-                <div class="tablecolumn2_field short_dynamicsize">
-                  <span wicket:id="poolMaxObjects">[poolMaxObjects]</span>
-                </div>
-              </div>
-              <div class="tablerow2">
-                <div class="tablecolumn2_label short_dynamicsize">
-                  <label for="poolMinIdle"><wicket:message key="poolMinIdle"/></label>
-                </div>
-                <div class="tablecolumn2_field short_dynamicsize">
-                  <span wicket:id="poolMinIdle">[poolMinIdle]</span>
-                </div>
-                <div class="tablecolumn2_label short_dynamicsize">
-                  <label for="poolMaxIdle"><wicket:message key="poolMaxIdle"/></label>
-                </div>
-                <div class="tablecolumn2_field short_dynamicsize">
-                  <span wicket:id="poolMaxIdle">[poolMaxIdle]</span>
-                </div>
-              </div>
-              <div class="tablerow2 alt">
-                <div class="tablecolumn2_label short_dynamicsize">
-                  <label for="poolMaxWait"><wicket:message key="poolMaxWait"/></label>
-                </div>
-                <div class="tablecolumn2_field short_dynamicsize">
-                  <span wicket:id="poolMaxWait">[poolMaxWait]</span>
-                </div>
-                <div class="tablecolumn2_label short_dynamicsize">
-                  <label for="poolMinEvictableIdleTime"><wicket:message key="poolMinEvictableIdleTime"/></label>
-                </div>
-                <div class="tablecolumn2_field short_dynamicsize">
-                  <span wicket:id="poolMinEvictableIdleTime">[poolMinEvictableIdleTime]</span>
-                </div>
-              </div>
-            </div>
-          </div>
-          <div id="tabs-2">
-            <div id="formtable">
-              <span wicket:id="container">
-                <div style="border-bottom: 10px">
-                  <div style="width: 40px; text-align: center; font-size: 7px">
-                    <label for="version"><wicket:message key="overridable"/></label>
-                  </div>
-                </div>
-                <form wicket:id="connectorPropForm">
-                  <div class="tablerow connectorProp" wicket:id="connectorProperties">
-                    <div class="tablecolumn_check" style="width: 27px; text-align: center; margin-right: 10px">
-                      <span wicket:id="connPropAttrOverridable">[connPropAttrOverridable]</span>
-                    </div>
-                    <div class="tablecolumn_connPropAttr">
-                      <span wicket:id="connPropAttrSchema">[connPropAttrSchema]</span>
-                    </div>
-                    <div class="tablecolumn_field veryshort_fixedsize">
-                      <span wicket:id="panel">[panel]</span>
-                    </div>
-                  </div>
-                  <div>
-                    <a style="position: absolute; top: 2px; right:20px;" wicket:id="check">
-                      <img src="img/ping.png"width="30" height="30"
-                           alt="ping" title="title" wicket:message="title:check"/>
-                    </a>
-                  </div>
-                </form>
-              </span>
-            </div>
-          </div>
-          <div id="tabs-3">
-            <span wicket:id="capabilitiesPalette"/>
-          </div>
-        </div>
-
-        <div style="margin: 20px 10px 0">
-          <input type="submit"
-                 class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
-                 wicket:id="apply"/>
-          <input type="button"
-                 class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
-                 wicket:id="cancel"/>
-        </div>
-      </form>
-    </div>
-  </wicket:extend>
-</html>

http://git-wip-us.apache.org/repos/asf/syncope/blob/a2051012/client/console/src/main/resources/org/apache/syncope/client/console/pages/ConnectorModalPage.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/pages/ConnectorModalPage.properties b/client/console/src/main/resources/org/apache/syncope/client/console/pages/ConnectorModalPage.properties
deleted file mode 100644
index 8500f1a..0000000
--- a/client/console/src/main/resources/org/apache/syncope/client/console/pages/ConnectorModalPage.properties
+++ /dev/null
@@ -1,43 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-tab1=General
-tab2=Configuration
-tab3=Capabilities
-displayName=Display name
-bundleName=Bundle name
-version=Version
-connRequestTimeout=Request timeout (sec)
-action=Action
-edit=Edit
-edit_attribute=Edit attribute
-serviceName=Service name
-endpoint=Endpoint
-title=Connector
-overridable=Overridable
-property=Property
-value=Value
-
-success_connection=Successful connection
-error_connection=Connection failure
-check=Check connection
-location=Location
-poolMaxObjects=Max objects (idle+active)
-poolMinIdle=Min idle objects
-poolMaxIdle=Max idle objects
-poolMaxWait=Max waiting time (msec)
-poolMinEvictableIdleTime=Min eviction time (msec)
-new=New

http://git-wip-us.apache.org/repos/asf/syncope/blob/a2051012/client/console/src/main/resources/org/apache/syncope/client/console/pages/ConnectorModalPage_it.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/pages/ConnectorModalPage_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/pages/ConnectorModalPage_it.properties
deleted file mode 100644
index 96080c3..0000000
--- a/client/console/src/main/resources/org/apache/syncope/client/console/pages/ConnectorModalPage_it.properties
+++ /dev/null
@@ -1,43 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-tab1=Generale
-tab2=Configurazione
-tab3=Capabilities
-bundleName=Bundle name
-version=Versione
-connRequestTimeout=Timeout richiesta (sec)
-action=Azione
-edit=Edit
-edit_attribute=Edit attribute
-serviceName=Nome servizio
-endpoint=Endpoint
-title=Connettore
-displayName=Nome visualizzato
-overridable=Sovrascrivibile
-property=Propriet\u00e0
-value=Valore
-
-success_connection=Connessione avvenuta con successo
-error_connection=Connessione non riuscita
-check=Verifica connessione
-location=Posizione
-poolMaxObjects=Max oggetti (attivi e non)
-poolMinIdle=Max oggetti attivi
-poolMaxIdle=Max oggetti inattivi
-poolMaxWait=Tempo max attesa
-poolMinEvictableIdleTime=Tempo min espulsione
-new=Nuovo

http://git-wip-us.apache.org/repos/asf/syncope/blob/a2051012/client/console/src/main/resources/org/apache/syncope/client/console/pages/ConnectorModalPage_pt_BR.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/pages/ConnectorModalPage_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/pages/ConnectorModalPage_pt_BR.properties
deleted file mode 100644
index b688216..0000000
--- a/client/console/src/main/resources/org/apache/syncope/client/console/pages/ConnectorModalPage_pt_BR.properties
+++ /dev/null
@@ -1,43 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-tab1=Geral
-tab2=Configura\u00e7\u00e3o
-tab3=Capacidades
-displayName=Mostrar Nome
-bundleName=Nome do Pacote
-version=Vers\u00e3o
-connRequestTimeout=Timeout da Requisi\u00e7\u00e3o (seg)
-action=A\u00e7\u00e3o
-edit=Alterar
-edit_attribute=Alterar Atributo
-serviceName=Nome de Servi\u00e7o
-endpoint=Endpoint
-title=Conector
-overridable=Alter\u00e1vel
-property=Propriedade
-value=Valor
-
-success_connection=Sucesso na Conex\u00e3o
-error_connection=Falha na Conex\u00e3o
-check=Verificar a Conex\u00e3o
-location=Localiza\u00e7\u00e3o
-poolMaxObjects=Max objects (idle+active)
-poolMinIdle=Min idle objects
-poolMaxIdle=Max idle objects
-poolMaxWait=Max waiting time (msec)
-poolMinEvictableIdleTime=Min eviction time (msec)
-new=Novo

http://git-wip-us.apache.org/repos/asf/syncope/blob/a2051012/client/console/src/main/resources/org/apache/syncope/client/console/panels/ConnectorModal.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/ConnectorModal.html b/client/console/src/main/resources/org/apache/syncope/client/console/panels/ConnectorModal.html
new file mode 100644
index 0000000..b85acb6
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/ConnectorModal.html
@@ -0,0 +1,161 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+  <wicket:extend>
+    <p class="ui-widget ui-corner-all ui-widget-header">
+        <span wicket:id="new"/>&nbsp;<wicket:message key="title"/>&nbsp;<span wicket:id="key"/>
+    </p>
+    <div style="margin: 5px;">
+      <form wicket:id="form">
+        <div id="tabs">
+          <ul>
+            <li class="tabs-selected"><a href="#tabs-1"><span><wicket:message key="tab1"/></span></a></li>
+            <li><a href="#tabs-2"><span><wicket:message key="tab2"/></span></a></li>
+            <li><a href="#tabs-3"><span><wicket:message key="tab3"/></span></a></li>
+          </ul>
+          <div id="tabs-1">
+            <div id="formtable">
+              <div class="tablerow alt">
+                <div class="tablecolumn_label short_dynamicsize">
+                  <label for="displayName"><wicket:message key="displayName"/></label>
+                </div>
+                <div class="tablecolumn_field short_dynamicsize">
+                  <span wicket:id="displayName">[displayName]</span>
+                </div>
+              </div>
+
+              <div class="tablerow">
+                <div class="tablecolumn_label short_dynamicsize">
+                  <label for="location"><wicket:message key="location"/></label>
+                </div>
+                <div class="tablecolumn_field short_dynamicsize">
+                  <span wicket:id="location">[location]</span>
+                </div>
+              </div>
+
+              <div class="tablerow alt">
+                <div class="tablecolumn_label short_dynamicsize">
+                  <label for="name"><wicket:message key="name"/></label>
+                </div>
+                <div class="tablecolumn_field medium_dynamicsize">
+                  <span wicket:id="connectorName">[connectorName]</span>
+                </div>
+              </div>
+
+              <div class="tablerow">
+                <div class="tablecolumn_label short_dynamicsize">
+                  <label for="version"><wicket:message key="version"/></label>
+                </div>
+                <div class="tablecolumn_field short_dynamicsize">
+                  <span wicket:id="version">[version]</span>
+                </div>
+              </div>
+            </div>
+            <div style="display: table; border: 1px solid #BBBBBB;">
+              <div class="tablerow2 alt">
+                <div class="tablecolumn2_label short_dynamicsize">
+                  <label for="connRequestTimeout"><wicket:message key="connRequestTimeout"/></label>
+                </div>
+                <div class="tablecolumn2_field short_dynamicsize">
+                  <span wicket:id="connRequestTimeout">[connRequestTimeout]</span>
+                </div>
+                <div class="tablecolumn2_label short_dynamicsize">
+                  <label for="poolMaxObjects"><wicket:message key="poolMaxObjects"/></label>
+                </div>
+                <div class="tablecolumn2_field short_dynamicsize">
+                  <span wicket:id="poolMaxObjects">[poolMaxObjects]</span>
+                </div>
+              </div>
+              <div class="tablerow2">
+                <div class="tablecolumn2_label short_dynamicsize">
+                  <label for="poolMinIdle"><wicket:message key="poolMinIdle"/></label>
+                </div>
+                <div class="tablecolumn2_field short_dynamicsize">
+                  <span wicket:id="poolMinIdle">[poolMinIdle]</span>
+                </div>
+                <div class="tablecolumn2_label short_dynamicsize">
+                  <label for="poolMaxIdle"><wicket:message key="poolMaxIdle"/></label>
+                </div>
+                <div class="tablecolumn2_field short_dynamicsize">
+                  <span wicket:id="poolMaxIdle">[poolMaxIdle]</span>
+                </div>
+              </div>
+              <div class="tablerow2 alt">
+                <div class="tablecolumn2_label short_dynamicsize">
+                  <label for="poolMaxWait"><wicket:message key="poolMaxWait"/></label>
+                </div>
+                <div class="tablecolumn2_field short_dynamicsize">
+                  <span wicket:id="poolMaxWait">[poolMaxWait]</span>
+                </div>
+                <div class="tablecolumn2_label short_dynamicsize">
+                  <label for="poolMinEvictableIdleTime"><wicket:message key="poolMinEvictableIdleTime"/></label>
+                </div>
+                <div class="tablecolumn2_field short_dynamicsize">
+                  <span wicket:id="poolMinEvictableIdleTime">[poolMinEvictableIdleTime]</span>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div id="tabs-2">
+            <div id="formtable">
+              <span wicket:id="container">
+                <div style="border-bottom: 10px">
+                  <div style="width: 40px; text-align: center; font-size: 7px">
+                    <label for="version"><wicket:message key="overridable"/></label>
+                  </div>
+                </div>
+                <form wicket:id="connectorPropForm">
+                  <div class="tablerow connectorProp" wicket:id="connectorProperties">
+                    <div class="tablecolumn_check" style="width: 27px; text-align: center; margin-right: 10px">
+                      <span wicket:id="connPropAttrOverridable">[connPropAttrOverridable]</span>
+                    </div>
+                    <div class="tablecolumn_connPropAttr">
+                      <span wicket:id="connPropAttrSchema">[connPropAttrSchema]</span>
+                    </div>
+                    <div class="tablecolumn_field veryshort_fixedsize">
+                      <span wicket:id="panel">[panel]</span>
+                    </div>
+                  </div>
+                  <div>
+                    <a style="position: absolute; top: 2px; right:20px;" wicket:id="check">
+                      <img src="img/ping.png"width="30" height="30"
+                           alt="ping" title="title" wicket:message="title:check"/>
+                    </a>
+                  </div>
+                </form>
+              </span>
+            </div>
+          </div>
+          <div id="tabs-3">
+            <span wicket:id="capabilitiesPalette"/>
+          </div>
+        </div>
+
+        <div style="margin: 20px 10px 0">
+          <input type="submit"
+                 class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
+                 wicket:id="apply"/>
+          <input type="button"
+                 class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
+                 wicket:id="cancel"/>
+        </div>
+      </form>
+    </div>
+  </wicket:extend>
+</html>

http://git-wip-us.apache.org/repos/asf/syncope/blob/a2051012/client/console/src/main/resources/org/apache/syncope/client/console/panels/ConnectorModal.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/ConnectorModal.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/ConnectorModal.properties
new file mode 100644
index 0000000..8500f1a
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/ConnectorModal.properties
@@ -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.
+tab1=General
+tab2=Configuration
+tab3=Capabilities
+displayName=Display name
+bundleName=Bundle name
+version=Version
+connRequestTimeout=Request timeout (sec)
+action=Action
+edit=Edit
+edit_attribute=Edit attribute
+serviceName=Service name
+endpoint=Endpoint
+title=Connector
+overridable=Overridable
+property=Property
+value=Value
+
+success_connection=Successful connection
+error_connection=Connection failure
+check=Check connection
+location=Location
+poolMaxObjects=Max objects (idle+active)
+poolMinIdle=Min idle objects
+poolMaxIdle=Max idle objects
+poolMaxWait=Max waiting time (msec)
+poolMinEvictableIdleTime=Min eviction time (msec)
+new=New

http://git-wip-us.apache.org/repos/asf/syncope/blob/a2051012/client/console/src/main/resources/org/apache/syncope/client/console/panels/ConnectorModal_it.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/ConnectorModal_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/ConnectorModal_it.properties
new file mode 100644
index 0000000..96080c3
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/ConnectorModal_it.properties
@@ -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.
+tab1=Generale
+tab2=Configurazione
+tab3=Capabilities
+bundleName=Bundle name
+version=Versione
+connRequestTimeout=Timeout richiesta (sec)
+action=Azione
+edit=Edit
+edit_attribute=Edit attribute
+serviceName=Nome servizio
+endpoint=Endpoint
+title=Connettore
+displayName=Nome visualizzato
+overridable=Sovrascrivibile
+property=Propriet\u00e0
+value=Valore
+
+success_connection=Connessione avvenuta con successo
+error_connection=Connessione non riuscita
+check=Verifica connessione
+location=Posizione
+poolMaxObjects=Max oggetti (attivi e non)
+poolMinIdle=Max oggetti attivi
+poolMaxIdle=Max oggetti inattivi
+poolMaxWait=Tempo max attesa
+poolMinEvictableIdleTime=Tempo min espulsione
+new=Nuovo

http://git-wip-us.apache.org/repos/asf/syncope/blob/a2051012/client/console/src/main/resources/org/apache/syncope/client/console/panels/ConnectorModal_pt_BR.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/ConnectorModal_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/ConnectorModal_pt_BR.properties
new file mode 100644
index 0000000..b688216
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/ConnectorModal_pt_BR.properties
@@ -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.
+tab1=Geral
+tab2=Configura\u00e7\u00e3o
+tab3=Capacidades
+displayName=Mostrar Nome
+bundleName=Nome do Pacote
+version=Vers\u00e3o
+connRequestTimeout=Timeout da Requisi\u00e7\u00e3o (seg)
+action=A\u00e7\u00e3o
+edit=Alterar
+edit_attribute=Alterar Atributo
+serviceName=Nome de Servi\u00e7o
+endpoint=Endpoint
+title=Conector
+overridable=Alter\u00e1vel
+property=Propriedade
+value=Valor
+
+success_connection=Sucesso na Conex\u00e3o
+error_connection=Falha na Conex\u00e3o
+check=Verificar a Conex\u00e3o
+location=Localiza\u00e7\u00e3o
+poolMaxObjects=Max objects (idle+active)
+poolMinIdle=Min idle objects
+poolMaxIdle=Max idle objects
+poolMaxWait=Max waiting time (msec)
+poolMinEvictableIdleTime=Min eviction time (msec)
+new=Novo