package de.twentyeleven.skysail.skysail.server.ext.osgideps; import java.awt.BorderLayout; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.JFrame; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.mxgraph.layout.hierarchical.mxHierarchicalLayout; import com.mxgraph.model.mxCell; import com.mxgraph.swing.mxGraphComponent; import com.mxgraph.view.mxGraph; public class JGraphOsgiServicesVisualizer extends JFrame { private static final long serialVersionUID = 7110246569384550189L; private static final Logger logger = LoggerFactory.getLogger(JGraphOsgiServicesVisualizer.class); private mxGraph graph; private Map<String, Object> verticesMap = new HashMap<String, Object>(); private mxGraphComponent graphComponent; public JGraphOsgiServicesVisualizer() { super("skysail OSGi services visualization"); } public void buildGraphFromOsgiContext(BundleContext bundleContext) { graph = new mxGraph(); // mxFastOrganicLayout layout = new mxFastOrganicLayout(graph); // mxCircleLayout layout = new mxCircleLayout(graph); mxHierarchicalLayout layout = new mxHierarchicalLayout(graph); // layout.setRadius(30); // layout.setMinDistanceLimit(10); // layout.setInitialTemp(10); // layout.setForceConstant(120); // layout.setDisableEdgeStyle(true); graphComponent = new mxGraphComponent(graph); Object parent = graph.getDefaultParent(); getContentPane().add(BorderLayout.CENTER, graphComponent); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(1000, 800); setVisible(true); List<Bundle> skysailBundles = determineSkysailBundles(bundleContext); ServiceReference[] allServiceReferences = getServiceReferences(bundleContext); createGraph(parent, skysailBundles, allServiceReferences); layout.execute(graph.getDefaultParent()); // mxGraphView view = graphComponent.getGraph().getView(); // int compLen = graphComponent.getWidth(); // int viewLen = (int) view.getGraphBounds().getWidth(); // view.setScale((double) compLen / viewLen * view.getScale()); } public void run() { } private List<Bundle> determineSkysailBundles(BundleContext bundleContext) { List<Bundle> relevantBundles = new ArrayList<Bundle>(); Bundle[] bundles = bundleContext.getBundles(); for (Bundle bundle : bundles) { if (bundle.getSymbolicName().contains("skysail")) { relevantBundles.add(bundle); } } return relevantBundles; } private ServiceReference[] getServiceReferences(BundleContext bundleContext) { ServiceReference[] allServiceReferences = new ServiceReference[0]; try { allServiceReferences = bundleContext.getAllServiceReferences(null, null); } catch (InvalidSyntaxException e) { // TODO Auto-generated catch block e.printStackTrace(); } return allServiceReferences; } private void createGraph(Object parent, List<Bundle> skysailBundles, ServiceReference[] allServiceReferences) { graph.getModel().beginUpdate(); try { addInitialVertices(parent, skysailBundles); addEdges(allServiceReferences); removeEdgesWithoutReferences(); } finally { graph.getModel().endUpdate(); } } private void addInitialVertices(Object parent, List<Bundle> skysailBundles) { for (Bundle bundle : skysailBundles) { addVertex(bundle); } } private void addVertex(Bundle bundle) { if (!verticesMap.containsKey(bundle.getSymbolicName())) { logger.info("adding {} to vertices", bundle.getSymbolicName()); String vertexName = bundle.getSymbolicName() + " [" + bundle.getBundleId() + "]"; Object vertex = graph.insertVertex(graph.getDefaultParent(), null, vertexName, 20, 20, 180, 30); verticesMap.put(bundle.getSymbolicName(), vertex); } } private void addEdges(ServiceReference[] allServiceReferences) { for (ServiceReference ref : allServiceReferences) { analyseServiceReference(ref); } } private void analyseServiceReference(ServiceReference ref) { Bundle registeringBundle = ref.getBundle(); Bundle[] usingBundles = ref.getUsingBundles(); if (usingBundles == null) { return; } logger.info("checking {} for services", registeringBundle.getSymbolicName()); addVertex(registeringBundle); for (Bundle referencingBundle : usingBundles) { if (!verticesMap.containsKey(referencingBundle.getSymbolicName())) { addVertex(registeringBundle); } String edgeLabel = getEdgeLabel(ref); graph.insertEdge(graph.getDefaultParent(), null, edgeLabel, verticesMap.get(referencingBundle.getSymbolicName()), verticesMap.get(registeringBundle.getSymbolicName())); } } private String getEdgeLabel(ServiceReference ref) { Long serviceId = (Long) ref.getProperty(Constants.SERVICE_ID); String[] serviceClass = (String[]) ref.getProperty(Constants.OBJECTCLASS); StringBuilder sb = new StringBuilder(); sb.append("ServiceID: "); sb.append(serviceId).append("\n"); if (serviceClass.length > 0) { for (String classname : serviceClass) { String[] split = classname.split("\\."); sb.append(split[split.length - 1]); sb.append(" / "); } sb.delete(sb.length() - 3, sb.length() - 1); } return sb.toString(); } private void removeEdgesWithoutReferences() { for (String bundleName : verticesMap.keySet()) { mxCell bundle = (mxCell) verticesMap.get(bundleName); Object[] allEdges = graph.getAllEdges(new mxCell[] { bundle }); if (allEdges.length == 0) { logger.info("removing vertex for '{}' as it does not have any edges attached", bundleName); // graph.removeCells(new mxCell[] { bundle }); } } } }