[SYNCOPE-156] websocket behavior improvement
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/9abd35a2 Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/9abd35a2 Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/9abd35a2 Branch: refs/heads/SYNCOPE-156 Commit: 9abd35a29dc8616e6268e6c525e421f02d026f66 Parents: 310b34a Author: fmartelli <[email protected]> Authored: Tue Aug 18 18:48:51 2015 +0200 Committer: fmartelli <[email protected]> Committed: Tue Aug 18 18:48:51 2015 +0200 ---------------------------------------------------------------------- .../client/console/topology/Topology.java | 180 +--------------- .../console/topology/WebSocketBehavior.java | 209 +++++++++++++++++++ .../provision/ProvisionWizardBuilder.java | 2 +- 3 files changed, 213 insertions(+), 178 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/syncope/blob/9abd35a2/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 c991a44..81ef360 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 @@ -18,25 +18,13 @@ */ 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.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.cxf.jaxrs.client.WebClient; @@ -49,10 +37,7 @@ import org.apache.syncope.common.lib.to.ConnInstanceTO; import org.apache.syncope.common.lib.to.ResourceTO; import org.apache.syncope.common.lib.types.Entitlement; import org.apache.syncope.common.rest.api.service.SyncopeService; -import org.apache.wicket.Application; import org.apache.wicket.Component; -import org.apache.wicket.Session; -import org.apache.wicket.ThreadContext; import org.apache.wicket.ajax.AbstractAjaxTimerBehavior; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.IAjaxIndicatorAware; @@ -65,9 +50,6 @@ import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.model.LoadableDetachableModel; -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 { @@ -149,7 +131,7 @@ public class Topology extends BasePage { } }; - private enum SupportedOperation { + protected enum SupportedOperation { CHECK_RESOURCE, CHECK_CONNECTOR, @@ -166,163 +148,7 @@ public class Topology extends BasePage { modal.setInitialWidth(RESOURCE_MODAL_WIN_WIDTH); modal.setCookieName("resource-modal"); - add(new WebSocketBehavior() { - - private static final long serialVersionUID = 1L; - - final Map<String, String> resources = new HashMap<String, String>(); - - final Set<String> runningResCheck = new HashSet<>(); - - final Map<Long, String> connectors = new HashMap<Long, String>(); - - final Set<Long> runningConnCheck = new HashSet<>(); - - @Override - protected void onMessage(final WebSocketRequestHandler handler, final TextMessage message) { - try { - final ObjectMapper mapper = new ObjectMapper(); - final JsonNode obj = mapper.readTree(message.getText()); - - final ExecutorService executorService = Executors.newFixedThreadPool(1); - - switch (SupportedOperation.valueOf(obj.get("kind").asText())) { - case CHECK_CONNECTOR: - final Long ckey = obj.get("target").asLong(); - - if (connectors.containsKey(ckey)) { - handler.push(connectors.get(ckey)); - } else { - handler.push(String.format("{ \"status\": \"%s\", \"target\": \"%s\"}", UNKNOWN, ckey)); - } - - synchronized (runningConnCheck) { - if (runningConnCheck.contains(ckey)) { - LOG.debug("Running connection check for connector {}", ckey); - } else { - runningConnCheck.add(ckey); - } - } - - executorService.execute(new ConnCheck(ckey)); - - break; - case CHECK_RESOURCE: - final String rkey = obj.get("target").asText(); - - if (resources.containsKey(rkey)) { - handler.push(resources.get(rkey)); - } else { - handler.push(String.format("{ \"status\": \"%s\", \"target\": \"%s\"}", UNKNOWN, rkey)); - } - - synchronized (runningResCheck) { - if (runningResCheck.contains(rkey)) { - LOG.debug("Running connection check for resource {}", rkey); - } else { - runningResCheck.add(rkey); - } - } - - executorService.execute(new ResCheck(rkey)); - - 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: - } - - executorService.shutdown(); - - } catch (IOException e) { - LOG.error("Eror managing websocket message", e); - } - } - - class ConnCheck implements Runnable { - - final Long key; - - private final Application application; - - private final Session session; - - public ConnCheck(final Long key) { - this.key = key; - this.application = Application.get(); - this.session = Session.exists() ? Session.get() : null; - } - - @Override - public void run() { - try { - ThreadContext.setApplication(application); - ThreadContext.setSession(session); - - String res; - try { - final ConnInstanceTO connector = connectorRestClient.read(key); - res = String.format("{ \"status\": \"%s\", \"target\": \"%s\"}", - connectorRestClient.check(connector) ? REACHABLE : UNREACHABLE, key); - } catch (Exception e) { - LOG.warn("Error checking connection for {}", key, e); - res = String.format("{ \"status\": \"%s\", \"target\": \"%s\"}", FAILURE, key); - } - - synchronized (runningConnCheck) { - connectors.put(key, res); - runningConnCheck.remove(key); - } - } finally { - ThreadContext.detach(); - } - } - } - - class ResCheck implements Runnable { - - final String key; - - private final Application application; - - private final Session session; - - public ResCheck(final String key) { - this.key = key; - this.application = Application.get(); - this.session = Session.exists() ? Session.get() : null; - } - - @Override - public void run() { - try { - ThreadContext.setApplication(application); - ThreadContext.setSession(session); - - String res; - try { - final ResourceTO resource = resourceRestClient.read(key); - res = String.format("{ \"status\": \"%s\", \"target\": \"%s\"}", - connectorRestClient.check(resource) ? REACHABLE : UNREACHABLE, key); - } catch (Exception e) { - LOG.warn("Error checking connection for {}", key, e); - res = String.format("{ \"status\": \"%s\", \"target\": \"%s\"}", FAILURE, key); - } - - synchronized (runningResCheck) { - resources.put(key, res); - runningResCheck.remove(key); - } - } finally { - ThreadContext.detach(); - } - } - } - }); + add(new WebSocketBehavior()); // ----------------------------------------- // Add Zoom panel @@ -713,7 +539,7 @@ public class Topology extends BasePage { resourceCreateEvent.getDisplayName(), resourceCreateEvent.getKind()); - ((List<TopologyNode>) newlyCreated.getModelObject()).add(node); + newlyCreated.getModelObject().add(node); resourceCreateEvent.getTarget().add(newlyCreatedContainer); resourceCreateEvent.getTarget().appendJavaScript(String.format( http://git-wip-us.apache.org/repos/asf/syncope/blob/9abd35a2/client/console/src/main/java/org/apache/syncope/client/console/topology/WebSocketBehavior.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/topology/WebSocketBehavior.java b/client/console/src/main/java/org/apache/syncope/client/console/topology/WebSocketBehavior.java new file mode 100644 index 0000000..7cd0ff5 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/topology/WebSocketBehavior.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.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.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import org.apache.syncope.client.console.rest.ConnectorRestClient; +import org.apache.syncope.client.console.rest.ResourceRestClient; +import org.apache.syncope.common.lib.to.ConnInstanceTO; +import org.apache.syncope.common.lib.to.ResourceTO; +import org.apache.wicket.Application; +import org.apache.wicket.Session; +import org.apache.wicket.ThreadContext; +import org.apache.wicket.protocol.ws.api.WebSocketRequestHandler; +import org.apache.wicket.protocol.ws.api.message.TextMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WebSocketBehavior extends org.apache.wicket.protocol.ws.api.WebSocketBehavior { + + private static final long serialVersionUID = 1L; + + protected static final Logger LOG = LoggerFactory.getLogger(WebSocketBehavior.class); + + private final Map<String, String> resources = new HashMap<String, String>(); + + private final Set<String> runningResCheck = new HashSet<>(); + + private final Map<Long, String> connectors = new HashMap<Long, String>(); + + private final Set<Long> runningConnCheck = new HashSet<>(); + + private final ConnectorRestClient connectorRestClient = new ConnectorRestClient(); + + private final ResourceRestClient resourceRestClient = new ResourceRestClient(); + + @Override + protected void onMessage(final WebSocketRequestHandler handler, final TextMessage message) { + try { + final ObjectMapper mapper = new ObjectMapper(); + final JsonNode obj = mapper.readTree(message.getText()); + + final ExecutorService executorService = Executors.newFixedThreadPool(1); + + switch (Topology.SupportedOperation.valueOf(obj.get("kind").asText())) { + case CHECK_CONNECTOR: + final Long ckey = obj.get("target").asLong(); + + if (connectors.containsKey(ckey)) { + handler.push(connectors.get(ckey)); + } else { + handler.push(String.format("{ \"status\": \"%s\", \"target\": \"%s\"}", UNKNOWN, ckey)); + } + + synchronized (runningConnCheck) { + if (runningConnCheck.contains(ckey)) { + LOG.debug("Running connection check for connector {}", ckey); + } else { + runningConnCheck.add(ckey); + } + } + + executorService.execute(new ConnCheck(ckey)); + + break; + case CHECK_RESOURCE: + final String rkey = obj.get("target").asText(); + + if (resources.containsKey(rkey)) { + handler.push(resources.get(rkey)); + } else { + handler.push(String.format("{ \"status\": \"%s\", \"target\": \"%s\"}", UNKNOWN, rkey)); + } + + synchronized (runningResCheck) { + if (runningResCheck.contains(rkey)) { + LOG.debug("Running connection check for resource {}", rkey); + } else { + runningResCheck.add(rkey); + } + } + + executorService.execute(new ResCheck(rkey)); + + 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: + } + + executorService.shutdown(); + + } catch (IOException e) { + LOG.error("Eror managing websocket message", e); + } + } + + class ConnCheck implements Runnable { + + private final Long key; + + private final Application application; + + private final Session session; + + public ConnCheck(final Long key) { + this.key = key; + this.application = Application.get(); + this.session = Session.exists() ? Session.get() : null; + } + + @Override + public void run() { + try { + ThreadContext.setApplication(application); + ThreadContext.setSession(session); + + String res; + try { + final ConnInstanceTO connector = connectorRestClient.read(key); + res = String.format("{ \"status\": \"%s\", \"target\": \"%s\"}", + connectorRestClient.check(connector) ? REACHABLE : UNREACHABLE, key); + } catch (Exception e) { + LOG.warn("Error checking connection for {}", key, e); + res = String.format("{ \"status\": \"%s\", \"target\": \"%s\"}", FAILURE, key); + } + + synchronized (runningConnCheck) { + connectors.put(key, res); + runningConnCheck.remove(key); + } + } finally { + ThreadContext.detach(); + } + } + } + + class ResCheck implements Runnable { + + private final String key; + + private final Application application; + + private final Session session; + + public ResCheck(final String key) { + this.key = key; + this.application = Application.get(); + this.session = Session.exists() ? Session.get() : null; + } + + @Override + public void run() { + try { + ThreadContext.setApplication(application); + ThreadContext.setSession(session); + + String res; + try { + final ResourceTO resource = resourceRestClient.read(key); + res = String.format("{ \"status\": \"%s\", \"target\": \"%s\"}", + connectorRestClient.check(resource) ? REACHABLE : UNREACHABLE, key); + } catch (Exception e) { + LOG.warn("Error checking connection for {}", key, e); + res = String.format("{ \"status\": \"%s\", \"target\": \"%s\"}", FAILURE, key); + } + + synchronized (runningResCheck) { + resources.put(key, res); + runningResCheck.remove(key); + } + } finally { + ThreadContext.detach(); + } + } + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/9abd35a2/client/console/src/main/java/org/apache/syncope/client/console/wizards/provision/ProvisionWizardBuilder.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/provision/ProvisionWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/provision/ProvisionWizardBuilder.java index 364bdb2..30a7bbc 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/provision/ProvisionWizardBuilder.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/provision/ProvisionWizardBuilder.java @@ -79,7 +79,7 @@ public class ProvisionWizardBuilder extends AjaxWizardBuilder<ProvisionTO> imple }, res), new Predicate<String>() { @Override - public boolean evaluate(String key) { + public boolean evaluate(final String key) { return !currentlyAdded.contains(key); } });
