package org.argeo.osgi.ui.explorer.views; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.eclipse.ui.TreeParent; import org.argeo.osgi.ui.explorer.OsgiExplorerPlugin; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.part.ViewPart; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.service.packageadmin.ExportedPackage; import org.osgi.service.packageadmin.PackageAdmin; /** Experimental The OSGi runtime from a module perspective. */ public class ModulesView extends ViewPart { private final static Log log = LogFactory.getLog(ModulesView.class); private TreeViewer viewer; private PackageAdmin packageAdmin; private Comparator exportedPackageComparator = new Comparator() { public int compare(ExportedPackage o1, ExportedPackage o2) { if (!o1.getName().equals(o2.getName())) return o1.getName().compareTo(o2.getName()); else return o1.getVersion().compareTo(o2.getVersion()); } }; @Override public void createPartControl(Composite parent) { viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); viewer.setContentProvider(new ModulesContentProvider()); viewer.setLabelProvider(new ModulesLabelProvider()); viewer.setInput(OsgiExplorerPlugin.getDefault().getBundle() .getBundleContext()); } @Override public void setFocus() { viewer.getTree().setFocus(); } private class ModulesContentProvider implements ITreeContentProvider { public Object[] getElements(Object inputElement) { return getChildren(inputElement); } public Object[] getChildren(Object parentElement) { if (parentElement instanceof BundleContext) { BundleContext bundleContext = (BundleContext) parentElement; Bundle[] bundles = bundleContext.getBundles(); TreeParent bundlesNode = new TreeParent("Bundles"); for (Bundle bundle : bundles) { if (bundle.getState() == Bundle.ACTIVE) bundlesNode.addChild(new BundleNode(bundle)); } // scan packages ServiceReference paSr = bundleContext .getServiceReference(PackageAdmin.class.getName()); // TODO: make a cleaner referencing packageAdmin = (PackageAdmin) bundleContext.getService(paSr); Bundle bundle1 = null; Bundle bundle2 = null; Map> importedPackages = new HashMap>(); Map> packages = new TreeMap>(); for (Bundle bundle : bundles) { if (bundle.getSymbolicName() .equals("org.argeo.security.ui")) bundle1 = bundle; if (bundle.getSymbolicName().equals( "org.argeo.security.equinox")) bundle2 = bundle; ExportedPackage[] pkgs = packageAdmin .getExportedPackages(bundle); if (pkgs != null) for (ExportedPackage pkg : pkgs) { if (!packages.containsKey(pkg.getName())) packages.put(pkg.getName(), new TreeSet( exportedPackageComparator)); Set expPackages = (Set) packages .get(pkg.getName()); expPackages.add(pkg); // imported for (Bundle b : pkg.getImportingBundles()) { if (bundle.getBundleId() != b.getBundleId()) { if (!importedPackages.containsKey(b)) importedPackages .put(b, new TreeSet( exportedPackageComparator)); Set impPackages = (Set) importedPackages .get(b); impPackages.add(pkg); } } } } TreeParent mPackageNode = new TreeParent("Multiple Packages"); // TreeParent aPackageNode = new TreeParent("All Packages"); for (String packageName : packages.keySet()) { Set pkgs = packages.get(packageName); if (pkgs.size() > 1) { MultiplePackagesNode mpn = new MultiplePackagesNode( packageName, pkgs); mPackageNode.addChild(mpn); // aPackageNode.addChild(mpn); } else { // aPackageNode.addChild(new ExportedPackageNode(pkgs // .iterator().next())); } } return new Object[] { bundlesNode, mPackageNode };// , // aPackageNode // }; } else if (parentElement instanceof TreeParent) { return ((TreeParent) parentElement).getChildren(); } else { return null; } } public Object getParent(Object element) { // TODO Auto-generated method stub return null; } public boolean hasChildren(Object element) { if (element instanceof TreeParent) { return ((TreeParent) element).hasChildren(); } return false; } public void dispose() { // TODO Auto-generated method stub } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // TODO Auto-generated method stub } } protected Map dependencySpace(Bundle bundle, Map> importedPackages, Map> traces) { log.debug("Dependency space for " + bundle.getSymbolicName()); Map space = new TreeMap(); fillDependencySpace(space, bundle, importedPackages, bundle.getSymbolicName(), traces); return space; } /** Recursive */ protected void fillDependencySpace(Map space, Bundle bundle, Map> importedPackages, String currTrace, Map> traces) { if (importedPackages.containsKey(bundle)) { Set imports = importedPackages.get(bundle); // log.debug("## Fill dependency space for " + bundle + " : "); for (ExportedPackage pkg : imports) { if (!traces.containsKey(pkg.getName())) traces.put(pkg.getName(), new TreeSet()); traces.get(pkg.getName()).add(currTrace); if (!space.containsKey(pkg.getName())) { space.put(pkg.getName(), pkg); Bundle exportingBundle = pkg.getExportingBundle(); // if (bundle.getBundleId() != // exportingBundle.getBundleId()) fillDependencySpace(space, exportingBundle, importedPackages, currTrace + " > " + exportingBundle.getSymbolicName(), traces); } } } } private class ModulesLabelProvider extends LabelProvider implements ITableLabelProvider { public Image getColumnImage(Object element, int columnIndex) { // TODO Auto-generated method stub return null; } public String getColumnText(Object element, int columnIndex) { return getText(element); } } class BundleNode extends TreeParent { private final Bundle bundle; public BundleNode(Bundle bundle) { super(bundle.getSymbolicName()); this.bundle = bundle; // Registered services ServiceReference[] registeredServices = bundle .getRegisteredServices(); if (registeredServices != null) { TreeParent registeredServicesNode = new TreeParent( "Registered Services"); addChild(registeredServicesNode); for (ServiceReference sr : registeredServices) { if (sr != null) registeredServicesNode .addChild(new ServiceReferenceNode(sr)); } } // Used services ServiceReference[] usedServices = bundle.getRegisteredServices(); if (usedServices != null) { TreeParent usedServicesNode = new TreeParent("Used Services"); addChild(usedServicesNode); for (ServiceReference sr : usedServices) { if (sr != null) usedServicesNode.addChild(new ServiceReferenceNode(sr)); } } } public Bundle getBundle() { return bundle; } } class ServiceReferenceNode extends TreeParent { private final ServiceReference serviceReference; public ServiceReferenceNode(ServiceReference serviceReference) { super(serviceReference.toString()); this.serviceReference = serviceReference; Bundle[] usedBundles = serviceReference.getUsingBundles(); if (usedBundles != null) { TreeParent usingBundles = new TreeParent("Using Bundles"); addChild(usingBundles); for (Bundle b : usedBundles) { if (b != null) usingBundles.addChild(new TreeParent(b .getSymbolicName())); } } TreeParent properties = new TreeParent("Properties"); addChild(properties); for (String key : serviceReference.getPropertyKeys()) { properties.addChild(new TreeParent(key + "=" + serviceReference.getProperty(key))); } } public ServiceReference getServiceReference() { return serviceReference; } } class MultiplePackagesNode extends TreeParent { private String packageName; private Set exportedPackages; public MultiplePackagesNode(String packageName, Set exportedPackages) { super(packageName); this.packageName = packageName; this.exportedPackages = exportedPackages; for (ExportedPackage pkg : exportedPackages) { addChild(new ExportedPackageNode(pkg)); } } } class ConflictingPackageNode extends TreeParent { private ExportedPackage exportedPackage; public ConflictingPackageNode(ExportedPackage exportedPackage) { super(exportedPackage.getName() + " - " + exportedPackage.getVersion() + " (" + exportedPackage.getExportingBundle() + ")"); this.exportedPackage = exportedPackage; TreeParent bundlesNode = new TreeParent("Dependent Bundles"); this.addChild(bundlesNode); Map bundles = new TreeMap(); for (Bundle b : exportedPackage.getImportingBundles()) { bundles.put(b.getSymbolicName(), b); } for (String key : bundles.keySet()) { addDependentBundles(bundlesNode, bundles.get(key)); } } } protected void addDependentBundles(TreeParent parent, Bundle bundle) { TreeParent bundleNode = new TreeParent(bundle.toString()); parent.addChild(bundleNode); Map bundles = new TreeMap(); ExportedPackage[] pkgs = packageAdmin.getExportedPackages(bundle); if (pkgs != null) for (ExportedPackage pkg : pkgs) { for (Bundle b : pkg.getImportingBundles()) { if (!bundles.containsKey(b.getSymbolicName()) && b.getBundleId() != bundle.getBundleId()) { bundles.put(b.getSymbolicName(), b); } } } for (String key : bundles.keySet()) { addDependentBundles(bundleNode, bundles.get(key)); } } class ExportedPackageNode extends TreeParent { private ExportedPackage exportedPackage; public ExportedPackageNode(ExportedPackage exportedPackage) { super(exportedPackage.getName() + " - " + exportedPackage.getVersion() + " (" + exportedPackage.getExportingBundle() + ")"); this.exportedPackage = exportedPackage; for (Bundle bundle : exportedPackage.getImportingBundles()) { addChild(new BundleNode(bundle)); } } } }