felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cziege...@apache.org
Subject svn commit: r1203551 [1/4] - in /felix/trunk/webconsole-plugins/servicediagnostics: ./ core/ core/src/ core/src/main/ core/src/main/resources/ core/src/main/resources/html/ core/src/main/resources/html/js/ core/src/main/scala/ core/src/main/scala/servi...
Date Fri, 18 Nov 2011 09:40:51 GMT
Author: cziegeler
Date: Fri Nov 18 09:40:49 2011
New Revision: 1203551

URL: http://svn.apache.org/viewvc?rev=1203551&view=rev
Log:
FELIX-3128 : A Service Diagnostics service and graphical WebConsole plugin

Added:
    felix/trunk/webconsole-plugins/servicediagnostics/   (with props)
    felix/trunk/webconsole-plugins/servicediagnostics/NOTICE.txt   (with props)
    felix/trunk/webconsole-plugins/servicediagnostics/README.txt   (with props)
    felix/trunk/webconsole-plugins/servicediagnostics/core/
    felix/trunk/webconsole-plugins/servicediagnostics/core/pom.xml   (with props)
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/index.html
  (with props)
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/graffle.js
  (with props)
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/graph.js
  (with props)
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/jquery.js
  (with props)
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/raphael-min.js
  (with props)
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/ServiceDiagnostics.scala
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/ServiceDiagnosticsPlugin.scala
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/Activator.scala
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/DMNotAvail.scala
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/DSNotAvail.scala
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/impl/ServiceDiagnosticsImpl.scala
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/webconsole/
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/webconsole/Servlet.scala
    felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/scala/servicediagnostics/webconsole/WebConsolePlugin.scala
    felix/trunk/webconsole-plugins/servicediagnostics/pom.xml   (with props)
    felix/trunk/webconsole-plugins/servicediagnostics/run.sh   (with props)
    felix/trunk/webconsole-plugins/servicediagnostics/sample/
    felix/trunk/webconsole-plugins/servicediagnostics/sample/pom.xml   (with props)
    felix/trunk/webconsole-plugins/servicediagnostics/sample/src/
    felix/trunk/webconsole-plugins/servicediagnostics/sample/src/main/
    felix/trunk/webconsole-plugins/servicediagnostics/sample/src/main/scala/
    felix/trunk/webconsole-plugins/servicediagnostics/sample/src/main/scala/servicediagnostics/
    felix/trunk/webconsole-plugins/servicediagnostics/sample/src/main/scala/servicediagnostics/sample/
    felix/trunk/webconsole-plugins/servicediagnostics/sample/src/main/scala/servicediagnostics/sample/FelixLauncher.scala
    felix/trunk/webconsole-plugins/servicediagnostics/sample/src/main/scala/servicediagnostics/sample/TestDM.scala
    felix/trunk/webconsole-plugins/servicediagnostics/sample/src/main/scala/servicediagnostics/sample/TestDS.scala

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Fri Nov 18 09:40:49 2011
@@ -0,0 +1,4 @@
+.settings
+.classpath
+.project
+target

Added: felix/trunk/webconsole-plugins/servicediagnostics/NOTICE.txt
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/servicediagnostics/NOTICE.txt?rev=1203551&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/servicediagnostics/NOTICE.txt (added)
+++ felix/trunk/webconsole-plugins/servicediagnostics/NOTICE.txt Fri Nov 18 09:40:49 2011
@@ -0,0 +1,9 @@
+This project is using third party javascript library, under core/src/main/resources/html/js
+- graffle.js
+- graph.js
+- jquery.js
+- raphael-min.js
+
+In my understanding, these are all MIT licences.
+
+This project also uses org.json, and the scala programming language. (Both need to be wrapped
into OSGi bundles, see README file)

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/NOTICE.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/NOTICE.txt
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/NOTICE.txt
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/trunk/webconsole-plugins/servicediagnostics/README.txt
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/servicediagnostics/README.txt?rev=1203551&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/servicediagnostics/README.txt (added)
+++ felix/trunk/webconsole-plugins/servicediagnostics/README.txt Fri Nov 18 09:40:49 2011
@@ -0,0 +1,64 @@
+OSGi Service Diagnostics and WebConsole Plugin
+==============================================
+
+This projects aims at easing diagnostics of OSGi services and finding about missing dependencies.
+
+Typically in a large system with many cascading dependencies managed by different trackers
such as DeclarativeService, DependencyManager or others, tracking the root cause of a top
level service not being started can become very cumbersome. When building service oriented
architectures, it is often the case that a single missing requirement will lock a full stack
of services, but to find that one requirement is like finding a needle in a haystack!
+
+The basic idea here is to ask each dependency manager instance about its unresolved dependencies,
merge all answers and filter the result to keep only the root causes. 
+
+Typically, if A depends on B which depends on C which depends on D, and D is nowhere to be
found, I need only show the "C -> D" missing requirement; if D is resolved, then the whole
stack is unlocked.
+
+Similarly, if D is known by another dependency management system, but unregistered because
it depends on E which is missing, then only the "D -> E" requirement is relevant. 
+
+Project organization (core):
+============================
+* servicediagnostics: the API package. It holds the main service interface as well as the
plugin interface, to extend to other dependency management systems
+
+* servicediagnostics.impl: the implementation package. It contains plugins implementations
for org.apache.felix.scr and org.apache.felix.dependencymanager, as well as the main service
implementation.
+
+* servicediagnostics.webconsole: a Felix WebConsole plugin that displays a graphical view
of the diagnostics result. Alternatively it can also show a graph of all services currently
registered in the service registry and the bundles using them. See Screenshot-notavail.png
and Screenshot-all.png. 
+
+The "sample" part simply contains some test classes and a helper class to launch Felix. 
+
+How to build the project:
+=========================
+
+> mvn install
+
+How to run:
+===========
+I'm providing a simple run script just to try out the service.
+Unfortunately, org.json and scala-library don't come readily packaged as OSGi bundles, so
we need to wrap them ourselves and copy these runtime dependencies into a "lib" directory
under the project root:
+lib/json-osgi.jar
+lib/scala-library-osgi.jar
+
+These libraries can be easily created using Bnd:
+> java -jar bnd.jar wrap $HOME/.m2/repository/org/scala-lang/scala-library/2.8.1/scala-library-2.8.1.jar
+> mv scala-library-2.8.1.bar lib/scala-library-osgi.jar
+
+> java -jar bnd.jar wrap $HOME/.m2/repository/org/json/json/20090211/json-20090211.jar
+> mv json-20090211.bar lib/json-osgi.jar
+
+Once this is done, you can simply run:
+> ./run.sh
+
+It should display:
+[INFO] Started jetty 6.1.x at port(s) HTTP:8080
+
+You can then point your browser to 
+http://localhost:8080/system/console/servicegraph
+
+(login/password is admin/admin)
+then click on either "Unavail" or "All". 
+The "bubbles" can be dragged around for better readability. The colors are random and don't
mean anything. 
+On the "All" view, arrows point from bundles to the services they use. 
+On the "Unavail" view, arrows point from a leaf component to its missing dependencies.
+
+(note: the lib directory is provided for dependencies that are not readily available as OSGi
bundles from maven)
+
+Issues & TODOs:
+===============
+* use of JSONObject in Servlet.scala is a bit awkward, but Scala's native json is still incomplete..

+* no support for service properties; needs to be added.
+* no support for iPojo, Blueprint, basic ServiceTrackers... more plugins could be developed.
I only wrote the ones i'm using.

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/README.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/README.txt
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/README.txt
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/trunk/webconsole-plugins/servicediagnostics/core/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/servicediagnostics/core/pom.xml?rev=1203551&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/servicediagnostics/core/pom.xml (added)
+++ felix/trunk/webconsole-plugins/servicediagnostics/core/pom.xml Fri Nov 18 09:40:49 2011
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>servicediagnostics</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <relativePath>../pom.xml</relativePath>
+  </parent>
+
+  <groupId>org.apache.felix</groupId>
+  <artifactId>servicediagnostics.core</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.webconsole</artifactId>
+      <version>3.1.8</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>javax.servlet</artifactId>
+      <version>1.0.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.json</groupId>
+      <artifactId>json</artifactId>
+      <version>20090211</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <instructions>
+            <Bundle-Category>osgi</Bundle-Category>
+            <Bundle-SymbolicName>
+              ${project.artifactId}
+            </Bundle-SymbolicName>
+            <Bundle-Activator>
+              org.apache.felix.servicediagnostics.impl.Activator
+            </Bundle-Activator>
+            <Export-Package>
+              org.apache.felix.servicediagnostics;version=1.0
+            </Export-Package>
+            <Private-Package>
+              org.apache.felix.servicediagnostics.impl,
+              org.apache.felix.servicediagnostics.webconsole
+            </Private-Package>
+            <Include-Resource>
+              src/main/resources
+            </Include-Resource>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  
+</project>

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/core/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/core/pom.xml
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/core/pom.xml
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 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=1203551&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/index.html
(added)
+++ felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/index.html
Fri Nov 18 09:40:49 2011
@@ -0,0 +1,147 @@
+<!--
+/*
+ * 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.
+ */
+-->
+<header>
+    <script type="text/javascript" src="/servicegraph/js/raphael-min.js"></script>
+    <script type="text/javascript" src="/servicegraph/js/graffle.js"></script>
+    <script type="text/javascript" src="/servicegraph/js/graph.js"></script>
+    <script type="text/javascript" src="/servicegraph/js/jquery.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); }
+
+var services;
+
+// from graph demo @ http://blog.ameisenbar.de/en/2010/03/02/dracula/
+function graphUnavail(json) {
+  var g = new Graph();
+
+  var empty = true;
+  for (s in json) {
+    empty = false;
+    for (i = 0; i < json[s].length; i++) {
+      // point unregistered service to dependency name
+      g.addEdge(s, json[s][i], { directed : true } );
+    }
+  }
+
+  if (empty) {
+    $("#canvas").empty().append($("<h1>").html("Service Registry status OK: No unresolved
service found."));
+  } 
+  else showGraph(g)
+}
+
+function graphAllServices(json) {
+  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
+      g.addEdge(json[s][i], s, { directed : true } );
+    }
+  }
+
+  if (empty) {
+    $("#canvas").empty().append($("<h1>").html("Service Registry empty: no service
found."));
+  }
+  else showGraph(g)
+}
+
+function showGraph(g) {
+    debug(g);
+
+    /* 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();
+    };
+}
+
+function redraw() {
+  var filter = $("#filter").val();
+  if (filter) {
+    var grep = {}; 
+    for (s in services) if (s.indexOf(filter) >= 0) grep[s] = services[s]; 
+    graphAllServices(grep);
+  } else {
+    graphAllServices(services);
+  }
+}
+
+function loadUnavail() {
+  $("#canvas").html("Loading data. Please wait...");
+  $.ajax({
+    url: "/servicegraph/json/notavail",
+    dataType: "json",
+    success: function(json){
+      services = json;
+      debug("Got services");
+      debug(json);
+      graphUnavail(json);
+    }
+  });
+}
+
+function loadAllServices() {
+  $("#canvas").html("Loading data. Please wait...");
+  $.ajax({
+    url: "/servicegraph/json/all",
+    dataType: "json",
+    success: function(json){
+      services = json;
+      debug("Got services");
+      debug(json);
+      graphAllServices(json);
+    }
+  });
+}
+
+/* only do all this when document has finished loading (needed for RaphaelJS) */
+$(document).ready(function(){
+  $("#actions")
+  	.append($("<a>").attr("href", "javascript:loadAllServices()").html("All"))
+  	.append($("<span>").html("|"))
+  	.append($("<a>").attr("href", "javascript:loadUnavail()").html("Unavail"))
+});
+
+-->
+    </script>
+</header>
+<body>
+Filter:&nbsp;<input type="text" id="filter"/><button id="redraw" onclick="redraw();">redraw</button>
+&nbsp;&nbsp;<span id="actions"></span>
+<div id="canvas"></div>
+</body>

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/index.html
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/index.html
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/index.html
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/graffle.js
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/graffle.js?rev=1203551&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/graffle.js
(added)
+++ felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/graffle.js
Fri Nov 18 09:40:49 2011
@@ -0,0 +1,101 @@
+/**
+ * Originally grabbed from the official RaphaelJS Documentation
+ * http://raphaeljs.com/graffle.html
+ * Changes and comments by Philipp Strathausen http://blog.ameisenbar.de
+ * Licenced under the MIT licence.
+ */
+
+/**
+ * Usage:
+ * connect two shapes
+ * parameters: 
+ *      source shape [or connection for redrawing], 
+ *      target shape,
+ *      style with { fg : linecolor, bg : background color, directed: boolean }
+ * returns:
+ *      connection { draw = function() }
+ */
+Raphael.fn.connection = function (obj1, obj2, style) {
+    var selfRef = this;
+    /* create and return new connection */
+    var color = style.fg || "#000";
+    var edge = {/*
+        from : obj1,
+        to : obj2,
+        style : style,*/
+        draw : function() {
+            /* get bounding boxes of target and source */
+            var bb1 = obj1.getBBox();
+            var bb2 = obj2.getBBox();
+            bb1.height = bb1.height + 15; /* respect the label TODO do it in a cleaner way
*/
+            bb2.height = bb2.height + 15;
+            var off1 = 1;
+            var off2 = 2;
+            /* coordinates for potential connection coordinates from/to the objects */
+            var p = [
+                {x: bb1.x + bb1.width / 2, y: bb1.y - off1},              /* NORTH 1 */
+                {x: bb1.x + bb1.width / 2, y: bb1.y + bb1.height + off1}, /* SOUTH 1 */
+                {x: bb1.x - off1, y: bb1.y + bb1.height / 2},             /* WEST  1 */
+                {x: bb1.x + bb1.width + off1, y: bb1.y + bb1.height / 2}, /* EAST  1 */
+                {x: bb2.x + bb2.width / 2, y: bb2.y - off2},              /* NORTH 2 */
+                {x: bb2.x + bb2.width / 2, y: bb2.y + bb2.height + off2}, /* SOUTH 2 */
+                {x: bb2.x - off2, y: bb2.y + bb2.height / 2},             /* WEST  2 */
+                {x: bb2.x + bb2.width + off2, y: bb2.y + bb2.height / 2}  /* EAST  2 */
+            ];
+            
+            /* distances between objects and according coordinates connection */
+            var d = {}, dis = [];
+
+            /*
+             * find out the best connection coordinates by trying all possible ways
+             */
+            /* loop the first object's connection coordinates */
+            for (var i = 0; i < 4; i++) {
+                /* loop the seond object's connection coordinates */
+                for (var j = 4; j < 8; j++) {
+                    var dx = Math.abs(p[i].x - p[j].x),
+                        dy = Math.abs(p[i].y - p[j].y);
+                    if ((i == j - 4) || (((i != 3 && j != 6) || p[i].x < p[j].x)
&& ((i != 2 && j != 7) || p[i].x > p[j].x) && ((i != 0 &&
j != 5) || p[i].y > p[j].y) && ((i != 1 && j != 4) || p[i].y < p[j].y)))
{
+                        dis.push(dx + dy);
+                        d[dis[dis.length - 1]] = [i, j];
+                    }
+                }
+            }
+            var res = dis.length == 0 ? res = [0, 4] : d[Math.min.apply(Math, dis)];
+            /* bezier path */
+            var x1 = p[res[0]].x,
+                y1 = p[res[0]].y,
+                x4 = p[res[1]].x,
+                y4 = p[res[1]].y,
+                dx = Math.max(Math.abs(x1 - x4) / 2, 10),
+                dy = Math.max(Math.abs(y1 - y4) / 2, 10),
+                x2 = [x1, x1, x1 - dx, x1 + dx][res[0]].toFixed(3),
+                y2 = [y1 - dy, y1 + dy, y1, y1][res[0]].toFixed(3),
+                x3 = [0, 0, 0, 0, x4, x4, x4 - dx, x4 + dx][res[1]].toFixed(3),
+                y3 = [0, 0, 0, 0, y1 + dy, y1 - dy, y4, y4][res[1]].toFixed(3);
+            /* assemble path and arrow */
+            var path = ["M", x1.toFixed(3), y1.toFixed(3), "C", x2, y2, x3, y3, x4.toFixed(3),
y4.toFixed(3)].join(",");
+            /* arrow */
+            if(style && style.directed) {
+                /* magnitude, length of the last path vector */
+                var mag = Math.sqrt((y4 - y3) * (y4 - y3) + (x4 - x3) * (x4 - x3));
+                /* vector normalisation to specified length  */
+                var norm = function(x,l){return (-x*(l||5)/mag);};
+                /* calculate array coordinates (two lines orthogonal to the path vector)
*/
+                var arr = [
+                    {x:(norm(x4-x3)+norm(y4-y3)+x4).toFixed(3), y:(norm(y4-y3)+norm(x4-x3)+y4).toFixed(3)},
+                    {x:(norm(x4-x3)-norm(y4-y3)+x4).toFixed(3), y:(norm(y4-y3)-norm(x4-x3)+y4).toFixed(3)}
+                ];
+                path = path + ",M"+arr[0].x+","+arr[0].y+",L"+x4+","+y4+",L"+arr[1].x+","+arr[1].y;

+            }
+            
+            // applying path
+            edge.fg && edge.fg.attr({path:path}) 
+                || (edge.fg = selfRef.path(path).attr({stroke: color, fill: "none"}).toBack());
+            edge.bg && edge.bg.attr({path:path})
+                || style && style.bg && (edge.bg = style.bg.split &&
selfRef.path(path).attr({stroke: style.bg.split("|")[0], fill: "none", "stroke-width": style.bg.split("|")[1]
|| 3}).toBack());
+        }
+    }
+    edge.draw();
+    return edge;
+};

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/graffle.js
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/graffle.js
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/graffle.js
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/graph.js
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/graph.js?rev=1203551&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/graph.js
(added)
+++ felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/graph.js
Fri Nov 18 09:40:49 2011
@@ -0,0 +1,303 @@
+/*  Graph JavaScript framework, version 0.0.1
+ *  (c) 2006 Aslak Hellesoy <aslak.hellesoy@gmail.com>
+ *  (c) 2006 Dave Hoover <dave.hoover@gmail.com>
+ *
+ *  Ported from Graph::Layouter::Spring in
+ *    http://search.cpan.org/~pasky/Graph-Layderer-0.02/
+ *  The algorithm is based on a spring-style layouter of a Java-based social
+ *  network tracker PieSpy written by Paul Mutton E<lt>paul@jibble.orgE<gt>.
+ *
+ *  Adopted by Philipp Strathausen <strathausen@gmail.com> to support Raphael JS
+ *  for rendering, dragging and much more. See http://blog.ameisenbar.de
+ *
+ *  Graph is freely distributable under the terms of an MIT-style license.
+ *  For details, see the Graph web site: http://dev.buildpatternd.com/trac
+ *
+ *  Links:
+ *
+ *  Demo of the original applet:
+ *      http://redsquirrel.com/dave/work/webdep/
+ *
+ *  Mirrored original source code at snipplr:
+ *      http://snipplr.com/view/1950/graph-javascript-framework-version-001/
+ *
+ *  Original usage example:
+ *      http://ajaxian.com/archives/new-javascriptcanvas-graph-library
+ *
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Graph
+ */
+var Graph = function() {
+    this.nodes = [];
+    this.edges = [];
+};
+Graph.prototype = {
+    addNode: function(id, content) {
+        /* testing if node is already existing in the graph */
+        var new_node = this.nodes[id];
+        if(new_node == undefined) {
+                new_node = new Graph.Node(id, content||{"id":id});
+                this.nodes[id] = new_node;
+                this.nodes.push(new_node); // TODO get rid of the array
+        }
+        return new_node;
+    },
+
+    addEdge: function(source, target, style) {
+        var s = this.addNode(source);
+        var t = this.addNode(target);
+        var color;
+        var colorbg;
+        var directed;
+        if(style) { color = style.color; colorbg = style.colorbg; directed = style.directed
}
+        var edge = { source: s, target: t, color: color, colorbg: colorbg, directed: directed
};
+        this.edges.push(edge);
+    }
+};
+
+/*
+ * Node
+ */
+Graph.Node = function(id, value){
+    this.id = id;
+    this.content = value;
+};
+Graph.Node.prototype = {
+};
+Graph.Renderer = {};
+Graph.Renderer.Raphael = function(element, graph, width, height) {
+    this.width = width||400;
+    this.height = height||400;
+    var selfRef = this;
+    this.r = Raphael(element, this.width, this.height);
+    this.radius = 40; /* max dimension of a node */
+    this.graph = graph;
+    this.mouse_in = false;
+    
+    /*
+     * Dragging
+     */
+    this.isDrag = false;
+    this.dragger = function (e) {
+        this.dx = e.clientX;
+        this.dy = e.clientY;
+        selfRef.isDrag = this;
+        this.animate({"fill-opacity": .2}, 500);
+        e.preventDefault && e.preventDefault();
+    };
+
+    document.onmousemove = function (e) {
+        e = e || window.event;
+        if (selfRef.isDrag) {
+            var newX = e.clientX - selfRef.isDrag.dx + (selfRef.isDrag.attrs.cx == null ?
(selfRef.isDrag.attrs.x + selfRef.isDrag.attrs.width / 2) : selfRef.isDrag.attrs.cx);
+            var newY = e.clientY - selfRef.isDrag.dy + (selfRef.isDrag.attrs.cy == null ?
(selfRef.isDrag.attrs.y + selfRef.isDrag.attrs.height / 2) : selfRef.isDrag.attrs.cy);
+            /* prevent shapes from being dragged out of the canvas */
+            var clientX = e.clientX - (newX < 20 ? newX - 20 : newX > selfRef.width
- 20 ? newX - selfRef.width + 20 : 0);
+            var clientY = e.clientY - (newY < 20 ? newY - 20 : newY > selfRef.height
- 20 ? newY - selfRef.height + 20 : 0);
+            selfRef.isDrag.translate(clientX - selfRef.isDrag.dx, clientY - selfRef.isDrag.dy);
+            selfRef.isDrag.label.translate(clientX - selfRef.isDrag.dx, clientY - selfRef.isDrag.dy);
+            for (var i in selfRef.graph.edges) {
+                selfRef.graph.edges[i].connection.draw();
+            }
+            //selfRef.r.safari();
+            selfRef.isDrag.dx = clientX;
+            selfRef.isDrag.dy = clientY;
+        }
+    };
+    document.onmouseup = function () {
+        selfRef.isDrag && selfRef.isDrag.animate({"fill-opacity": 0}, 500);
+        selfRef.isDrag = false;
+    };
+};
+
+/*
+ * Renderer using RaphaelJS
+ */
+Graph.Renderer.Raphael.prototype = {
+    translate: function(point) {
+        return [
+            (point[0] - this.graph.layoutMinX) * this.factorX + this.radius,
+            (point[1] - this.graph.layoutMinY) * this.factorY + this.radius
+        ];
+    },
+
+    rotate: function(point, length, angle) {
+        var dx = length * Math.cos(angle);
+        var dy = length * Math.sin(angle);
+        return [point[0]+dx, point[1]+dy];
+    },
+
+    draw: function() {
+        this.factorX = (width - 2 * this.radius) / (this.graph.layoutMaxX - this.graph.layoutMinX);
+        this.factorY = (height - 2 * this.radius) / (this.graph.layoutMaxY - this.graph.layoutMinY);
+        for (var i = 0; i < this.graph.nodes.length; i++) {
+            this.drawNode(this.graph.nodes[i]);
+        }
+        for (var i = 0; i < this.graph.edges.length; i++) {
+            this.drawEdge(this.graph.edges[i]);
+        }
+    },
+    drawNode: function(node) {
+        var point = this.translate([node.layoutPosX, node.layoutPosY]);
+        node.point = point;
+        
+        /* if node has already been drawn, move the nodes */
+        if(node.shape) {
+//            console.log(node.shape.attrs );
+            var opoint = [ node.shape.attrs.cx || node.shape.attrs.x + node.shape.attrs.width
/ 2 , node.shape.attrs.cy || node.shape.attrs.y + node.shape.attrs.height / 2 + 15 ];
+            node.shape.translate(point[0]-opoint[0], point[1]-opoint[1]);
+            node.shape.label.translate(point[0]-opoint[0], point[1]-opoint[1]);
+            this.r.safari();
+            return;
+        }
+        var shape;
+        if(node.content.getShape) {
+            shape = node.content.getShape(this.r, point[0], point[1]);
+            shape.attr({"fill-opacity": 0});
+        } else {
+            shape = this.r.ellipse(point[0], point[1], 30, 20);
+            var color = Raphael.getColor();
+            shape.attr({fill: color, stroke: color, "fill-opacity": 0, "stroke-width": 2})
+        }
+        shape.mousedown(this.dragger);
+        shape.node.style.cursor = "move";
+        shape.label = this.r.text(point[0], point[1] + 30, node.content.label || node.id);
// Beware: operator || also considers values like -1, 0, ...
+        node.shape = shape;
+    },
+    drawEdge: function(edge) {
+        /* if edge already has been drawn, only refresh the edge */
+        edge.connection && edge.connection.draw();
+        if(!edge.connection)
+            edge.connection = this.r.connection(edge.source.shape, edge.target.shape, { fg:
edge.color, bg: edge.colorbg, directed: edge.directed });
+    }
+};
+Graph.Layout = {};
+Graph.Layout.Spring = function(graph) {
+                this.graph = graph;
+                this.iterations = 500;
+                this.maxRepulsiveForceDistance = 6;
+                this.k = 2;
+                this.c = 0.01;
+                this.maxVertexMovement = 0.5;
+        };
+Graph.Layout.Spring.prototype = {
+        layout: function() {
+                this.layoutPrepare();
+            for (var i = 0; i < this.iterations; i++) {
+                        this.layoutIteration();
+                }
+                this.layoutCalcBounds();
+        },
+       
+        layoutPrepare: function() {
+            for (var i = 0; i < this.graph.nodes.length; i++) {
+                    var node = this.graph.nodes[i];
+                        node.layoutPosX = 0;
+                        node.layoutPosY = 0;
+                        node.layoutForceX = 0;
+                        node.layoutForceY = 0;
+                }
+                
+        },
+       
+        layoutCalcBounds: function() {
+                var minx = Infinity, maxx = -Infinity, miny = Infinity, maxy = -Infinity;
+
+            for (var i = 0; i < this.graph.nodes.length; i++) {
+                        var x = this.graph.nodes[i].layoutPosX;
+                        var y = this.graph.nodes[i].layoutPosY;
+                                               
+                        if(x > maxx) maxx = x;
+                        if(x < minx) minx = x;
+                        if(y > maxy) maxy = y;
+                        if(y < miny) miny = y;
+                }
+
+                this.graph.layoutMinX = minx;
+                this.graph.layoutMaxX = maxx;
+                this.graph.layoutMinY = miny;
+                this.graph.layoutMaxY = maxy;
+        },
+       
+        layoutIteration: function() {
+                // Forces on nodes due to node-node repulsions
+            for (var i = 0; i < this.graph.nodes.length; i++) {
+                    var node1 = this.graph.nodes[i];
+                    for (var j = i + 1; j < this.graph.nodes.length; j++) {
+                            var node2 = this.graph.nodes[j];
+                                this.layoutRepulsive(node1, node2);
+                        }
+                }
+                // Forces on nodes due to edge attractions
+            for (var i = 0; i < this.graph.edges.length; i++) {
+                    var edge = this.graph.edges[i];
+                        this.layoutAttractive(edge);             
+                }
+               
+                // Move by the given force
+            for (var i = 0; i < this.graph.nodes.length; i++) {
+                    var node = this.graph.nodes[i];
+                        var xmove = this.c * node.layoutForceX;
+                        var ymove = this.c * node.layoutForceY;
+
+                        var max = this.maxVertexMovement;
+                        if(xmove > max) xmove = max;
+                        if(xmove < -max) xmove = -max;
+                        if(ymove > max) ymove = max;
+                        if(ymove < -max) ymove = -max;
+                       
+                        node.layoutPosX += xmove;
+                        node.layoutPosY += ymove;
+                        node.layoutForceX = 0;
+                        node.layoutForceY = 0;
+                }
+        },
+
+        layoutRepulsive: function(node1, node2) {
+                var dx = node2.layoutPosX - node1.layoutPosX;
+                var dy = node2.layoutPosY - node1.layoutPosY;
+                var d2 = dx * dx + dy * dy;
+                if(d2 < 0.01) {
+                        dx = 0.1 * Math.random() + 0.1;
+                        dy = 0.1 * Math.random() + 0.1;
+                        var d2 = dx * dx + dy * dy;
+                }
+                var d = Math.sqrt(d2);
+                if(d < this.maxRepulsiveForceDistance) {
+                        var repulsiveForce = this.k * this.k / d;
+                        node2.layoutForceX += repulsiveForce * dx / d;
+                        node2.layoutForceY += repulsiveForce * dy / d;
+                        node1.layoutForceX -= repulsiveForce * dx / d;
+                        node1.layoutForceY -= repulsiveForce * dy / d;
+                }
+        },
+
+        layoutAttractive: function(edge) {
+                var node1 = edge.source;
+                var node2 = edge.target;
+               
+                var dx = node2.layoutPosX - node1.layoutPosX;
+                var dy = node2.layoutPosY - node1.layoutPosY;
+                var d2 = dx * dx + dy * dy;
+                if(d2 < 0.01) {
+                        dx = 0.1 * Math.random() + 0.1;
+                        dy = 0.1 * Math.random() + 0.1;
+                        var d2 = dx * dx + dy * dy;
+                }
+                var d = Math.sqrt(d2);
+                if(d > this.maxRepulsiveForceDistance) {
+                        d = this.maxRepulsiveForceDistance;
+                        d2 = d * d;
+                }
+                var attractiveForce = (d2 - this.k * this.k) / this.k;
+                if(edge.weight == undefined || edge.weight < 1) edge.weight = 1;
+                attractiveForce *= Math.log(edge.weight) * 0.5 + 1;
+               
+                node2.layoutForceX -= attractiveForce * dx / d;
+                node2.layoutForceY -= attractiveForce * dy / d;
+                node1.layoutForceX += attractiveForce * dx / d;
+                node1.layoutForceY += attractiveForce * dy / d;
+        }
+};

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/graph.js
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/graph.js
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: felix/trunk/webconsole-plugins/servicediagnostics/core/src/main/resources/html/js/graph.js
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message