You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ap...@apache.org on 2013/07/11 13:37:15 UTC

svn commit: r1502190 - in /felix/trunk/webconsole-plugins/servicediagnostics: ./ core/ core/src/main/resources/html/ core/src/main/resources/html/js/ core/src/main/scala/servicediagnostics/impl/ core/src/main/scala/servicediagnostics/shell/ core/src/ma...

Author: apanday
Date: Thu Jul 11 11:37:14 2013
New Revision: 1502190

URL: http://svn.apache.org/r1502190
Log:
support optional loops in CLI and logical expressions in graph filter + js cleanup

Added:
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/diagnostics.js
Modified:
    felix/trunk/webconsole-plugins/servicediagnostics/changelog.txt
    felix/trunk/webconsole-plugins/servicediagnostics/core/pom.xml
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/index.html
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/Activator.scala
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/ServiceDiagnosticsImpl.scala
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/shell/CLI.scala
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/webconsole/WebConsolePlugin.scala

Modified: felix/trunk/webconsole-plugins/servicediagnostics/changelog.txt
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/servicediagnostics/changelog.txt?rev=1502190&r1=1502189&r2=1502190&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/servicediagnostics/changelog.txt (original)
+++ felix/trunk/webconsole-plugins/servicediagnostics/changelog.txt Thu Jul 11 11:37:14 2013
@@ -13,6 +13,7 @@ Changes from 0.1.2 to 0.1.3
   * new visualisations of the service registry: service providers, using
   bundles, and bundles wiring via services
   * show components as implementations and services as interfaces
+  * graph filter supports basic logical expressions
 
 Changes from 0.1.1 to 0.1.2
 ---------------------------

Modified: felix/trunk/webconsole-plugins/servicediagnostics/core/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/servicediagnostics/core/pom.xml?rev=1502190&r1=1502189&r2=1502190&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/servicediagnostics/core/pom.xml (original)
+++ felix/trunk/webconsole-plugins/servicediagnostics/core/pom.xml Thu Jul 11 11:37:14 2013
@@ -100,6 +100,7 @@
             <exclude>src/main/resources/html/js/raphael-1.3.1.min.js</exclude>
             <exclude>src/main/resources/html/js/graffle-1.3.1.js</exclude>
             <exclude>src/main/resources/html/js/graph.js</exclude>
+            <exclude>src/main/resources/html/js/diagnostics.js</exclude>
           </excludes>
         </configuration>
       </plugin>

Modified: felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/index.html
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/index.html?rev=1502190&r1=1502189&r2=1502190&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/index.html (original)
+++ felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/index.html Thu Jul 11 11:37:14 2013
@@ -18,246 +18,33 @@
  * under the License.
  */
 -->
-    <script type="text/javascript">
+<script type="text/javascript" src="servicegraph/html/js/raphael-1.3.1.min.js"></script>
+<script type="text/javascript" src="servicegraph/html/js/graffle-1.3.1.js"></script>
+<script type="text/javascript" src="servicegraph/html/js/graph.js"></script>
+<script type="text/javascript" src="servicegraph/html/js/diagnostics.js"></script>
+<script type="text/javascript">
 <!--
 
-var _redraw
-var height = 600
-var width = 1000
-
-DEBUG = false
-debug = function (obj) { if(DEBUG && console) console.debug(obj) }
-
-function isEmpty(obj) { 
-  for (var key in obj) return false 
-  return true
-}
-
-var services
-var grapher
-
-// from graph demo @ http://blog.ameisenbar.de/en/2010/03/02/dracula/
-function graphUnavail(json) {
-  $("#legend").html("Bubbles are components, dotted squares are missing required dependencies.")
-  var g = new Graph()
-
-  var empty = true
-  notavail = json.notavail
-  for (s in notavail) {
-    empty = false
-    for (i = 0; i < notavail[s].length; i++) {
-      // point unregistered service to dependency name
-      var dep = notavail[s][i]
-      g.addNode(dep, {
-        getShape : function(r,x,y) {
-          // create a dashed square shape to differentiate the missing dependency
-          return r.rect(x-30, y-13, 62, 33, 5).attr({
-            "fill": "#f00", 
-            "stroke": "gray", 
-            "stroke-width": 2, 
-            "stroke-dasharray": "--"
-          })
-        }
-      })
-      g.addEdge(s, dep, { directed : true } )
-    }
-  }
-  // warn unresolved
-  if (json.unresolved && !isEmpty(json.unresolved)) 
-    $("#warning").html("circular dependencies detected! <a href='javascript:graphUnresolved()'>(show)</a>")
-  else 
-    $("#warning").html("") //clear previous
-
-  if (empty) {
-    $("#canvas").empty().append($("<h1>").html("Service Registry status OK: No unresolved service found."))
-  } 
-  else showGraph(g)
-}
-
-function graphUnresolved() {
-  grapher = graphUnresolved
-  $("#legend").html("Bubbles are unresolvable components linked to each other.")
-  var g = new Graph()
-  var unresolved = services.unresolved
-  for (s in unresolved) {
-    for (i = 0; i < unresolved[s].length; i++) {
-      g.addEdge(s, unresolved[s][i], { directed : true } )
-    }
-  }
-  showGraph(g)
-}
-
-function graphUsingServices(json) {
-  $("#legend").html("Black squares are bundles, pointing to the services they use.")
-  var g = new Graph()
-
-  var empty = true
-  for (s in json) {
-    empty = false
-    for (i = 0; i < json[s].length; i++) {
-      // point using bundle to service name
-      var bundle = json[s][i]
-      g.addNode(bundle, {
-        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": 2})
-        }
-      })
-      g.addEdge(bundle, s, { directed : true } )
-    }
-  }
-
-  if (empty) {
-    $("#canvas").empty().append($("<h1>").html("Service Registry empty: no service found."))
-  }
-  else showGraph(g)
-}
-
-function graphServiceProviders(json) {
-  $("#legend").html("Black squares are bundles, pointing to the services they provide.")
-  var g = new Graph()
-
-  var empty = true
-  for (bundle in json) {
-    empty = false
-    g.addNode(bundle, {
-      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": 2})
-      }
-    })
-    for (i = 0; i < json[bundle].length; i++) {
-      // point bundle to service name
-      var service = json[bundle][i]
-      g.addEdge(bundle, service, { directed : true } )
-    }
-  }
-
-  if (empty) {
-    $("#canvas").empty().append($("<h1>").html("Service Registry empty: no service found."))
-  }
-  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("")
-
-    /* layout the graph using the Spring layout implementation */
-    var layouter = new Graph.Layout.Spring(g)
-    layouter.layout()
-    
-    /* draw the graph using the RaphaelJS draw implementation */
-    $("#canvas").empty()
-    var renderer = new Graph.Renderer.Raphael('canvas', g, width, height)
-    renderer.draw()
-    
-    _redraw = function() {
-        layouter.layout()
-        renderer.draw()
-    }
-    $("#filterdiv").show()
-}
-
-function redraw() {
-  var filter = $("#filter").val()
-  if (filter) {
-    var grep = {}
-    for (s in services) if (s.indexOf(filter) >= 0) grep[s] = services[s]
-    grapher(grep)
-  } else {
-    grapher(services)
-  }
-}
-
-function loadUnavail() {
-  var withOpt = ""
-  if ($("#optionals").attr("checked")) withOpt = "?optionals=true"
-  grapher = graphUnavail
-  loadServices("notavail"+withOpt)
-}
-
-function loadServiceProviders() {
-  grapher = graphServiceProviders
-  loadServices("providing")
-}
-
-function loadServiceUsers() {
-  grapher = graphUsingServices
-  loadServices("using")
-}
-
-function loadB2B() {
-  grapher = graphB2B
-  loadServices("b2b")
-}
-
-function loadServices(cmd) {
-  $("#canvas").html("Loading data. Please wait...")
-  $.ajax({
-    url: "servicegraph/"+cmd,
-    dataType: "json",
-    success: function(json){
-      services = json
-      debug("Got services")
-      debug(json)
-      grapher(json)
-    }
-  })
-}
-
 /* only do all this when document has finished loading (needed for RaphaelJS) */
 $(document).ready(function(){
-    $.getScript("servicegraph/html/js/raphael-1.3.1.min.js")
-    $.getScript("servicegraph/html/js/graffle-1.3.1.js")
-    $.getScript("servicegraph/html/js/graph.js")
     $("#actions")
-  	.append($("<a>").attr("href", "javascript:loadServiceProviders()").html("Show Service Providers"))
-  	.append($("<span>").html("&nbsp;|&nbsp;"))
-  	.append($("<a>").attr("href", "javascript:loadServiceUsers()").html("Show Service Users"))
-  	.append($("<span>").html("&nbsp;|&nbsp;"))
-  	.append($("<a>").attr("href", "javascript:loadB2B()").html("Show Bundles Dependencies"))
-  	.append($("<span>").html("&nbsp;|&nbsp;"))
-  	.append($("<a>").attr("href", "javascript:loadUnavail()").html("Show Not Avail"))
-  	.append($("<span>").html("&nbsp;"))
-        .append($("<input>").attr("id", "optionals").attr("type", "checkbox"))
-        .append($("<span>").html("Include optionals in loops"))
+      .append($("<a>").attr("href", "javascript:Providers.load()").html("Show Service Providers"))
+      .append($("<span>").html("&nbsp;|&nbsp;"))
+      .append($("<a>").attr("href", "javascript:Users.load()").html("Show Service Users"))
+      .append($("<span>").html("&nbsp;|&nbsp;"))
+      .append($("<a>").attr("href", "javascript:B2B.load()").html("Show Bundles Dependencies"))
+      .append($("<span>").html("&nbsp;|&nbsp;"))
+      .append($("<a>").attr("href", "javascript:Unavail.load()").html("Show Not Avail"))
+      .append($("<span>").html("&nbsp;("))
+      .append($("<input>").attr("id", "optionals").attr("type", "checkbox"))
+      .append($("<span>").html("Include optionals in loop detection)"))
+    width = document.width
+    height = document.height
+    
 })
 
 -->
-    </script>
+</script>
     <style>
       #actions a { color:black; font-weight:bold; text-decoration:none; }
       #warning { color:red; font-weight:bold; }
@@ -265,7 +52,10 @@ $(document).ready(function(){
     </style>
 <div id="servicegraph">
 <span id="actions"></span>&nbsp;&nbsp;<span id="warning"></span>
-<div id="filterdiv">Filter:&nbsp;<input type="text" id="filter"/><button id="redraw" onclick="redraw();">redraw</button></div>
+<div id="filterdiv">
+  Filter:&nbsp;<input type="text" id="filter"/><button id="redraw" onclick="SD.doFilter();">redraw</button>
+  &nbsp;(Supports basic logical expressions with !,&amp;,|, like "felix &amp; !http")
+</div>
 <div><span id="legend"></span>&nbsp;<span>(All nodes can be dragged around)</span></div>
 <div id="canvas"></div>
 </div>

Added: felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/diagnostics.js
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/diagnostics.js?rev=1502190&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/diagnostics.js (added)
+++ felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/diagnostics.js Thu Jul 11 11:37:14 2013
@@ -0,0 +1,249 @@
+var DEBUG = false
+var debug = function (obj) { if(DEBUG && console) console.debug(obj) }
+
+function isEmpty(obj) { 
+  for (var key in obj) return false 
+  return true
+}
+function grep(source, f) {
+  var greped = {}
+  for (s in source) if (match(s, f.trim())) greped[s] = source[s]
+  return greped
+}
+
+function match(s,f) {
+  if (f.charAt(0) == "!") 
+    return (s.indexOf(f.replace("!","")) < 0)
+  else 
+    return (s.indexOf(f) >= 0)
+}
+
+
+var SD = {
+  json: {},
+  grapher: {},
+
+  draw: function(source) {
+    this.grapher.draw(source)
+  },
+
+  loadServices: function (cmd, grapher) {
+    $("#warning").html("")
+    $("#canvas").html("Loading data. Please wait...")
+    $.ajax({
+      url: "servicegraph/"+cmd,
+      dataType: "json",
+      success: function(json){
+        debug("Got services")
+        debug(json)
+        SD.json = json
+        SD.grapher = grapher
+        grapher.draw(json)
+      },
+      error: function() {
+        alert("request failed on servicegraph/"+cmd)
+      }
+    })
+  },
+
+  doFilter: function () {
+    var filter = $("#filter").val()
+    if (filter) {
+      var split = filter.split(" ")
+      var greped = {}
+      var action = ""
+      $(split).each(function(i,e) {
+        var tok = e.trim()
+        if (tok == "&" || tok == "|") {
+          action = tok
+        }
+        else if (action == "&") {
+          greped = grep(greped, tok)
+        }
+        else if (action == "|") {
+          var grepf = grep(SD.json, tok)
+          for (s in grepf) greped[s] = grepf[s]
+        }
+        else greped = grep(SD.json, tok)
+      })
+      SD.draw(greped)
+    } else {
+      SD.draw(SD.json)
+    }
+  },
+
+  showGraffle: function (g) {
+      debug(g)
+
+      /* layout the graph using the Spring layout implementation */
+      new Graph.Layout.Spring(g).layout()
+      
+      /* draw the graph using the RaphaelJS draw implementation */
+      $("#canvas").empty()
+      new Graph.Renderer.Raphael('canvas', g, width, height).draw()
+      
+      $("#filterdiv").show()
+  }
+}
+
+Unavail = {
+  load: function() {
+    var withOpt = ""
+    if ($("#optionals").attr("checked")) withOpt = "?optionals=true"
+    SD.loadServices("notavail"+withOpt, this)
+  },
+
+  draw: function(json) {
+    $("#legend").html("Bubbles are components, dotted squares are missing required dependencies.")
+    var g = new Graph()
+
+    var empty = true
+    notavail = json.notavail
+    for (s in notavail) {
+      empty = false
+      for (i = 0; i < notavail[s].length; i++) {
+        // point unregistered service to dependency name
+        var dep = notavail[s][i]
+        g.addNode(dep, {
+          getShape : function(r,x,y) {
+            // create a dashed square shape to differentiate the missing dependency
+            return r.rect(x-30, y-13, 62, 33, 5).attr({
+              "fill": "#f00", 
+              "stroke": "gray", 
+              "stroke-width": 2, 
+              "stroke-dasharray": "--"
+            })
+          }
+        })
+        g.addEdge(s, dep, { directed : true } )
+      }
+    }
+    // warn unresolved
+    if (json.unresolved && !isEmpty(json.unresolved)) 
+      $("#warning").html("circular dependencies detected! <a href='javascript:SD.grapher=Loops; Loops.draw(SD.json)'>(show)</a>")
+    else 
+      $("#warning").html("") //clear previous
+
+    if (empty) {
+      $("#canvas").empty().append($("<h1>").html("Service Registry status OK: No unresolved service found."))
+    } 
+    else SD.showGraffle(g)
+  }
+}
+
+
+Loops = {
+  draw: function(json) {
+    $("#legend").html("Bubbles are unresolvable components linked to each other.")
+    var g = new Graph()
+    var unresolved = json.unresolved
+    for (s in unresolved) {
+      for (i = 0; i < unresolved[s].length; i++) {
+        g.addEdge(s, unresolved[s][i], { directed : true } )
+      }
+    }
+    SD.showGraffle(g)
+  }
+}
+
+Users = {
+  load: function() {
+    SD.loadServices("users", this)
+  },
+
+  draw: function(json) {
+    $("#legend").html("Black squares are bundles, pointing to the services they use.")
+    var g = new Graph()
+
+    var empty = true
+    for (s in json) {
+      empty = false
+      for (i = 0; i < json[s].length; i++) {
+        // point using bundle to service name
+        var bundle = json[s][i]
+        g.addNode(bundle, {
+          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": 2})
+          }
+        })
+        g.addEdge(bundle, s, { directed : true } )
+      }
+    }
+
+    if (empty) {
+      $("#canvas").empty().append($("<h1>").html("Service Registry empty: no service found."))
+    }
+    else SD.showGraffle(g)
+  }
+}
+
+Providers = {
+  load: function() {
+    SD.loadServices("providers", this)
+  },
+
+  draw: function(json) {
+    $("#legend").html("Black squares are bundles, pointing to the services they provide.")
+    var g = new Graph()
+
+    var empty = true
+    for (bundle in json) {
+      empty = false
+      g.addNode(bundle, {
+        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": 2})
+        }
+      })
+      for (i = 0; i < json[bundle].length; i++) {
+        // point bundle to service name
+        var service = json[bundle][i]
+        g.addEdge(bundle, service, { directed : true } )
+      }
+    }
+
+    if (empty) {
+      $("#canvas").empty().append($("<h1>").html("Service Registry empty: no service found."))
+    }
+    else SD.showGraffle(g)
+  }
+}
+
+B2B = {
+  load: function() {
+    SD.loadServices("b2b", this)
+  },
+
+  draw: function(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({"fill": "#f00", "stroke-width": 2})
+          }
+        })
+        g.addEdge(user, provider, { directed : true } )
+      }
+    }
+
+    if (empty) {
+      $("#canvas").empty().append($("<h1>").html("Service Registry empty: no service found."))
+    }
+    else SD.showGraffle(g)
+  }
+}

Modified: felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/Activator.scala
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/Activator.scala?rev=1502190&r1=1502189&r2=1502190&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/Activator.scala (original)
+++ felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/Activator.scala Thu Jul 11 11:37:14 2013
@@ -77,8 +77,8 @@ class Activator extends DependencyActiva
         // register the shell command
         dm.add(createComponent
             .setInterface(classOf[Command].getName, new jHT[String,Any]() {{
-                  put(CommandProcessor.COMMAND_FUNCTION, Array("notavail", "circular"))
-                  put(CommandProcessor.COMMAND_SCOPE, "sd")
+                  put(CommandProcessor.COMMAND_FUNCTION, CLI.usage.split("|"))
+                  put(CommandProcessor.COMMAND_SCOPE, CLI.scope)
               }})
             .setImplementation(classOf[CLI])
             .add(createServiceDependency

Modified: felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/ServiceDiagnosticsImpl.scala
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/ServiceDiagnosticsImpl.scala?rev=1502190&r1=1502189&r2=1502190&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/ServiceDiagnosticsImpl.scala (original)
+++ felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/ServiceDiagnosticsImpl.scala Thu Jul 11 11:37:14 2013
@@ -65,10 +65,12 @@ class ServiceDiagnosticsImpl(val bc:Bund
     }
 
     //debug helper
-    def json(l:Iterable[Node]) = l.toList.foldLeft(new org.json.JSONArray()) { (j,n) => 
-      j.put(new org.json.JSONObject(new java.util.HashMap[String,java.util.List[String]] {{
-          put(n.name, new java.util.ArrayList[String] {{ addAll(n.edges.map(_.name)) }})
-        }}))
+    def json(l:Iterable[Node]) = l.toList.sortWith { (n1,n2) => 
+        n1.name < n2.name
+    }.foldLeft(new org.json.JSONArray()) { (j,n) => 
+        j.put(new org.json.JSONObject(new java.util.HashMap[String,java.util.List[String]] {{
+            put(n.name, new java.util.ArrayList[String] {{ addAll(n.edges.map(_.name)) }})
+          }}))
     }.toString(2)
 
     /**

Modified: felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/shell/CLI.scala
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/shell/CLI.scala?rev=1502190&r1=1502189&r2=1502190&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/shell/CLI.scala (original)
+++ felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/shell/CLI.scala Thu Jul 11 11:37:14 2013
@@ -27,37 +27,52 @@ import java.io.PrintStream
 // gogo shell
 import org.apache.felix.service.command.Descriptor
 
+// constants
+object CLI {
+    val scope = "sd"
+    val usage = "notavail|loops|users|providers|b2b"
+    val description = """Service Diagnostics
+        |sd notavail: dumps a summary of leaf missing dependencies as a json map of component to list of dependencies
+        |sd loops [-o]: checks for unresolvable components (typically circular dependencies). -o to include optionals.
+        |sd users: dumps service usage as a json map of service to list of using bundles 
+        |sd providers: dumps service providers as a json map of bundle to list of services
+        |sd b2b: shows bundle to bundle links via service usage (merged users and providers) as a json map of provider to list of users
+        |""".stripMargin
+}
 class CLI extends Command
 {
     var engine:ServiceDiagnostics = _ //dependency injection. see Activator.
 
-    override def getName = "sd"
-    override def getShortDescription = "Service Diagnostics"
-    override def getUsage = "notavail|loops|using|providing|b2b"
+    override def getName = CLI.scope
+    override def getShortDescription = CLI.description
+    override def getUsage = CLI.usage
 
     // for gogo
-    def using = execute("sd using", System.out, System.err)
-    def providing = execute("sd providing", System.out, System.err)
+    def users = execute("sd users", System.out, System.err)
+    def providers = execute("sd providers", 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)
 
     // for old shell
     override def execute(commandLine:String, out:PrintStream, err:PrintStream) = commandLine.split(" ").toList.tail match {
-        case "using"::Nil => 
+        case "users"::Nil => 
             out.println(json(engine.usingBundles).toString(2))
-        case "providing"::Nil => 
+        case "providers"::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)
+        case "loops"::tail => tail match {
+            case "-o"::Nil => showloops(out, true)
+            case _  => showloops(out, false)
+        }
       case _ => err.println(getUsage)
     }
 
-    def showloops(out:PrintStream) = {
-        val unresolved = engine.unresolved(false) // map(comp -> list(comp))
+    def showloops(out:PrintStream, o:Boolean) = {
+        val unresolved = engine.unresolved(o) // map(comp -> list(comp))
         out.println(json(unresolved).toString(2))
         def follow(n:String, stack:Set[String] = Set()) :Set[String] = 
             if (stack contains n) stack 
@@ -66,7 +81,7 @@ class CLI extends Command
                 case Some(list) => list.toSet.flatMap { (d:String) => follow(d, stack+n) }
             }
         unresolved.keySet.map(follow(_)).foreach { loop => 
-            if (loop.size > 1 && unresolved(loop.last) == loop.head) 
+            if (loop.size > 1 && unresolved(loop.last).contains(loop.head))
                 out.println(loop.mkString("", " -> ", " -> "+loop.head)) 
         }
     }

Modified: felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/webconsole/WebConsolePlugin.scala
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/webconsole/WebConsolePlugin.scala?rev=1502190&r1=1502189&r2=1502190&view=diff
==============================================================================
--- felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/webconsole/WebConsolePlugin.scala (original)
+++ felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/webconsole/WebConsolePlugin.scala Thu Jul 11 11:37:14 2013
@@ -54,8 +54,8 @@ class WebConsolePlugin extends SimpleWeb
      */
     override def doGet(req:HttpServletRequest, resp:HttpServletResponse) = 
         req.getPathInfo match {
-            case "/servicegraph/using" => resp.getWriter.println(json(engine.usingBundles))
-            case "/servicegraph/providing" => resp.getWriter.println(json(engine.serviceProviders))
+            case "/servicegraph/users" => resp.getWriter.println(json(engine.usingBundles))
+            case "/servicegraph/providers" => 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))