added view of bundle to bundle wiring via services
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1500028 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole-plugins/servicediagnostics/changelog.txt b/webconsole-plugins/servicediagnostics/changelog.txt
index db86269..fffa2b4 100644
--- a/webconsole-plugins/servicediagnostics/changelog.txt
+++ b/webconsole-plugins/servicediagnostics/changelog.txt
@@ -10,8 +10,9 @@
* [FELIX-3769] webconsole categories
* [FELIX-4163] command line interface
* circular dependencies shown on a separate graph with or wihtout optionals
- * show both using bundles and providing bundles
- * show components as implementations ans services as interfaces
+ * new visualisations of the service registry: service providers, using
+ bundles, and bundles wiring via services
+ * show components as implementations and services as interfaces
Changes from 0.1.1 to 0.1.2
---------------------------
diff --git a/webconsole-plugins/servicediagnostics/core/src/main/resources/html/index.html b/webconsole-plugins/servicediagnostics/core/src/main/resources/html/index.html
index 68af2f6..adc416f 100644
--- a/webconsole-plugins/servicediagnostics/core/src/main/resources/html/index.html
+++ b/webconsole-plugins/servicediagnostics/core/src/main/resources/html/index.html
@@ -139,6 +139,38 @@
else showGraph(g)
}
+function graphB2B(json) {
+ $("#legend").html("Black squares are bundles, pointing to the bundles they use for their services.")
+ var g = new Graph()
+
+ var empty = true
+ for (provider in json) {
+ empty = false
+ g.addNode(provider, {
+ getShape : function(r,x,y) {
+ // create a square shape to differentiate bundles from services
+ return r.rect(x-30, y-13, 62, 33, 5).attr({"fill": "#f00", "stroke-width": 1})
+ }
+ })
+ for (i = 0; i < json[provider].length; i++) {
+ // point using bundle to provider bundle
+ var user = json[provider][i]
+ g.addNode(user, {
+ getShape : function(r,x,y) {
+ // create a square shape to differentiate bundles from services
+ return r.rect(x-30, y-13, 62, 33, 5).attr({"stroke-width": 2})
+ }
+ })
+ g.addEdge(user, provider, { directed : true } )
+ }
+ }
+
+ if (empty) {
+ $("#canvas").empty().append($("<h1>").html("Service Registry empty: no service found."))
+ }
+ else showGraph(g)
+}
+
function showGraph(g) {
debug(g)
$("#warning").html("")
@@ -187,6 +219,11 @@
loadServices("using")
}
+function loadB2B() {
+ grapher = graphB2B
+ loadServices("b2b")
+}
+
function loadServices(cmd) {
$("#canvas").html("Loading data. Please wait...")
$.ajax({
@@ -211,6 +248,8 @@
.append($("<span>").html(" | "))
.append($("<a>").attr("href", "javascript:loadServiceUsers()").html("Show Service Users"))
.append($("<span>").html(" | "))
+ .append($("<a>").attr("href", "javascript:loadB2B()").html("Show Bundles Dependencies"))
+ .append($("<span>").html(" | "))
.append($("<a>").attr("href", "javascript:loadUnavail()").html("Show Not Avail"))
.append($("<span>").html(" "))
.append($("<input>").attr("id", "optionals").attr("type", "checkbox"))
diff --git a/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/ServiceDiagnostics.scala b/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/ServiceDiagnostics.scala
index 77e5756..85eb4af 100644
--- a/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/ServiceDiagnostics.scala
+++ b/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/ServiceDiagnostics.scala
@@ -28,22 +28,28 @@
/**
* returns a map of component name to list of leaf unresolved dependencies.
*/
- def notavail:Map[String, List[String]]
+ def notavail:Map[String, Set[String]]
/**
* returns a graph of unresolvable components (typically loops)
* @param optionals if true, include optional services in loop detection
*/
- def unresolved(optionals:Boolean) :Map[String, List[String]]
+ def unresolved(optionals:Boolean) :Map[String, Set[String]]
/**
* returns a map of resolved service names to list of bundles using the service
*/
- def usingBundles:Map[String, List[String]]
+ def usingBundles:Map[String, Set[String]]
/**
* returns a map of bundle names to list of provided services
*/
- def serviceProviders:Map[String, List[String]]
+ def serviceProviders:Map[String, Set[String]]
+
+ /**
+ * shows service links between bundles
+ * returns a map of bundle names to list of bundles using its services
+ */
+ def b2b:Map[String, Set[String]]
}
diff --git a/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/ServiceDiagnosticsPlugin.scala b/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/ServiceDiagnosticsPlugin.scala
index 3a33dca..7a22cac 100644
--- a/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/ServiceDiagnosticsPlugin.scala
+++ b/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/ServiceDiagnosticsPlugin.scala
@@ -96,6 +96,6 @@
/**
* turn the ServiceDiagnostics output into a JSON representation.
*/
- def json(map:Map[String,List[String]]) =
- new JSONObject(asJavaMap(mMap() ++ map.map(kv => (kv._1, asJavaList(kv._2)))))
+ def json(map:Map[String,Set[String]]) =
+ new JSONObject(asJavaMap(mMap() ++ map.map(kv => (kv._1, asJavaList(kv._2.toList)))))
}
diff --git a/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/ServiceDiagnosticsImpl.scala b/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/ServiceDiagnosticsImpl.scala
index 17903ce..5c27780 100644
--- a/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/ServiceDiagnosticsImpl.scala
+++ b/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/ServiceDiagnosticsImpl.scala
@@ -47,11 +47,11 @@
* and filters all intermediate known unregistered services
* to keep only missing "leaf" dependencies
*/
- override def notavail :Map[String, List[String]] =
+ override def notavail :Map[String, Set[String]] =
{
val unavail = plugins.flatMap(_.components).filterNot(_.registered)
- unavail.foldLeft(Map[String,List[String]]()) { (map,comp) =>
- val missing = comp.deps.filterNot { d =>
+ unavail.foldLeft(Map[String,Set[String]]()) { (map,comp) =>
+ val missing = comp.deps.toSet.filterNot { d =>
d.available || unavail.exists(c => d.matchedBy(c))
}.map(_.toString)
if (missing isEmpty) map else map + (shorten(comp.impl) -> missing)
@@ -82,7 +82,7 @@
* from the original graph. This is done because "perfect loops" have no border node and are
* therefore "invisible" to the traversing algorithm.
*/
- override def unresolved(optionals:Boolean) :Map[String, List[String]] =
+ override def unresolved(optionals:Boolean) :Map[String, Set[String]] =
{
// first build a traversable graph from all found components and dependencies
def buildGraph(link:(Node,Node)=>Unit) = {
@@ -138,16 +138,16 @@
// finally filter the original graph by removing all resolved nodes
// and format the result (keeping only the names)
(for (node <- graph.filterNot(n => n.edges.isEmpty || resolved.contains(n)))
- yield (node.name -> node.edges.map{ n => n.name }.toList)).toMap
+ yield (node.name -> node.edges.map{ n => n.name }.toSet)).toMap
}
/**
* Implements ServiceDiagnostics.usingBundles.
*/
- override def usingBundles:Map[String,List[String]] =
- allServices.foldLeft(Map[String,List[String]]()) { case (result, (name, ref)) =>
+ override def usingBundles:Map[String,Set[String]] =
+ allServices.foldLeft(Map[String,Set[String]]()) { case (result, (name, ref)) =>
Option(ref.getUsingBundles).map { _.toList.map(_.toString) }.getOrElse(Nil) match {
- case using @ h::t => result + (name -> using)
+ case using @ h::t => result + (name -> using.toSet)
case Nil => result
}
}
@@ -155,10 +155,22 @@
/**
* Implements ServiceDiagnostics.serviceProviders.
*/
- override def serviceProviders:Map[String, List[String]] =
- allServices.foldLeft(Map[String,List[String]]()) { case (result, (name, ref)) =>
+ override def serviceProviders:Map[String, Set[String]] =
+ allServices.foldLeft(Map[String,Set[String]]()) { case (result, (name, ref)) =>
val b = ref.getBundle.toString
- result.updated(b, name :: result.getOrElse(b, Nil))
+ result.updated(b, result.getOrElse(b, Set()) + name)
+ }
+
+ override def b2b:Map[String,Set[String]] =
+ allServices.foldLeft(Map[String,Set[String]]()) { case (result, (name, ref)) =>
+ Option(ref.getUsingBundles).map { _.toList.map(_.toString) }.getOrElse(Nil) match {
+ case using @ h::t =>
+ val b = ref.getBundle.toString
+ val filteredUsers = using.filter(_ != b)
+ if (filteredUsers isEmpty) result
+ else result.updated(b, result.getOrElse(b, Set()) ++ using)
+ case Nil => result
+ }
}
/**
diff --git a/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/shell/CLI.scala b/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/shell/CLI.scala
index c3189d6..a78a8a9 100644
--- a/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/shell/CLI.scala
+++ b/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/shell/CLI.scala
@@ -33,11 +33,12 @@
override def getName = "sd"
override def getShortDescription = "Service Diagnostics"
- override def getUsage = "notavail|loops|using|providing"
+ override def getUsage = "notavail|loops|using|providing|b2b"
// for gogo
def using = execute("sd using", System.out, System.err)
def providing = execute("sd providing", System.out, System.err)
+ def b2b = execute("sd b2b", System.out, System.err)
def notavail = execute("sd notavail", System.out, System.err)
def loops = execute("sd loops", System.out, System.err)
@@ -47,6 +48,8 @@
out.println(json(engine.usingBundles).toString(2))
case "providing"::Nil =>
out.println(json(engine.serviceProviders).toString(2))
+ case "b2b"::Nil =>
+ out.println(json(engine.b2b).toString(2))
case "notavail"::Nil =>
out.println(json(engine.notavail).toString(2))
case "loops"::Nil => showloops(out)
diff --git a/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/webconsole/WebConsolePlugin.scala b/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/webconsole/WebConsolePlugin.scala
index 34d181f..530e14c 100644
--- a/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/webconsole/WebConsolePlugin.scala
+++ b/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/webconsole/WebConsolePlugin.scala
@@ -56,6 +56,7 @@
req.getPathInfo match {
case "/servicegraph/using" => resp.getWriter.println(json(engine.usingBundles))
case "/servicegraph/providing" => resp.getWriter.println(json(engine.serviceProviders))
+ case "/servicegraph/b2b" => resp.getWriter.println(json(engine.b2b))
case "/servicegraph/notavail" => resp.getWriter.println(new JSONObject()
.put("notavail", json(engine.notavail))
.put("unresolved",