Improve OSGi Explorer
authorMathieu Baudier <mbaudier@argeo.org>
Sat, 14 Feb 2015 13:30:27 +0000 (13:30 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Sat, 14 Feb 2015 13:30:27 +0000 (13:30 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@7867 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

org.argeo.eclipse.ui.workbench/icons/service_published.gif [new file with mode: 0644]
org.argeo.eclipse.ui.workbench/icons/service_referenced.gif [new file with mode: 0644]
org.argeo.eclipse.ui.workbench/plugin.xml
org.argeo.eclipse.ui.workbench/src/org/argeo/eclipse/ui/workbench/osgi/BundleNode.java [new file with mode: 0644]
org.argeo.eclipse.ui.workbench/src/org/argeo/eclipse/ui/workbench/osgi/BundlesView.java
org.argeo.eclipse.ui.workbench/src/org/argeo/eclipse/ui/workbench/osgi/ModulesView.java
org.argeo.eclipse.ui.workbench/src/org/argeo/eclipse/ui/workbench/osgi/MultiplePackagesView.java [new file with mode: 0644]
org.argeo.eclipse.ui.workbench/src/org/argeo/eclipse/ui/workbench/osgi/OsgiExplorerImages.java
org.argeo.eclipse.ui.workbench/src/org/argeo/eclipse/ui/workbench/osgi/ServiceReferenceNode.java [new file with mode: 0644]
org.argeo.eclipse.ui.workbench/src/org/argeo/eclipse/ui/workbench/osgi/StateLabelProvider.java [new file with mode: 0644]

diff --git a/org.argeo.eclipse.ui.workbench/icons/service_published.gif b/org.argeo.eclipse.ui.workbench/icons/service_published.gif
new file mode 100644 (file)
index 0000000..17f771a
Binary files /dev/null and b/org.argeo.eclipse.ui.workbench/icons/service_published.gif differ
diff --git a/org.argeo.eclipse.ui.workbench/icons/service_referenced.gif b/org.argeo.eclipse.ui.workbench/icons/service_referenced.gif
new file mode 100644 (file)
index 0000000..c24a95f
Binary files /dev/null and b/org.argeo.eclipse.ui.workbench/icons/service_referenced.gif differ
index be3cb43e68368176df3710aafe0b222e80e3137a..5e140f4180fcdfef61e68b4a052c022f66738860 100644 (file)
     <extension point="org.eclipse.ui.perspectiveExtensions"> 
         <perspectiveExtension targetID="org.argeo.eclipse.ui.workbench.osgiPerspective"> 
             <view 
-               id="org.argeo.eclipse.ui.workbench.bundlesView" 
+               id="org.argeo.eclipse.ui.workbench.modulesView" 
                minimized="false"
                ratio="0.5" 
                relationship="left" 
                relative="org.eclipse.ui.editorss"/> 
             <view 
-               id="org.argeo.eclipse.ui.workbench.modulesView" 
+               id="org.argeo.eclipse.ui.workbench.bundlesView" 
+               minimized="false"
+               relationship="stack" 
+               relative="org.argeo.eclipse.ui.workbench.modulesView"/> 
+             <view 
+               id="org.argeo.eclipse.ui.workbench.multiplePackagesView" 
                minimized="false"
                relationship="stack" 
                relative="org.argeo.eclipse.ui.workbench.bundlesView"/> 
@@ -41,7 +46,7 @@
                <view
                name="Modules"
             id="org.argeo.eclipse.ui.workbench.modulesView"
-            icon="icons/bundles.gif"
+            icon="icons/service_published.gif"
                        class="org.argeo.eclipse.ui.workbench.osgi.ModulesView">
                </view>
                <view
             class="org.argeo.eclipse.ui.workbench.osgi.BundlesView">
                </view>
                <view
+               name="Multiple Packages"
+            id="org.argeo.eclipse.ui.workbench.multiplePackagesView" 
+            icon="icons/node.gif"
+            class="org.argeo.eclipse.ui.workbench.osgi.MultiplePackagesView">
+               </view>
+               <view
           name="JCR Browser"
           id="org.argeo.eclipse.ui.workbench.jcrBrowserView"
           icon="icons/browser.gif"
diff --git a/org.argeo.eclipse.ui.workbench/src/org/argeo/eclipse/ui/workbench/osgi/BundleNode.java b/org.argeo.eclipse.ui.workbench/src/org/argeo/eclipse/ui/workbench/osgi/BundleNode.java
new file mode 100644 (file)
index 0000000..8661331
--- /dev/null
@@ -0,0 +1,46 @@
+package org.argeo.eclipse.ui.workbench.osgi;
+
+import org.argeo.eclipse.ui.TreeParent;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+
+/** A tree element representing a {@link Bundle} */
+class BundleNode extends TreeParent {
+       private final Bundle bundle;
+
+       public BundleNode(Bundle bundle) {
+               this(bundle, false);
+       }
+
+       @SuppressWarnings("rawtypes")
+       public BundleNode(Bundle bundle, boolean hasChildren) {
+               super(bundle.getSymbolicName());
+               this.bundle = bundle;
+
+               if (hasChildren) {
+                       // REFERENCES
+                       ServiceReference[] usedServices = bundle.getServicesInUse();
+                       if (usedServices != null) {
+                               for (ServiceReference sr : usedServices) {
+                                       if (sr != null)
+                                               addChild(new ServiceReferenceNode(sr, false));
+                               }
+                       }
+
+                       // SERVICES
+                       ServiceReference[] registeredServices = bundle
+                                       .getRegisteredServices();
+                       if (registeredServices != null) {
+                               for (ServiceReference sr : registeredServices) {
+                                       if (sr != null)
+                                               addChild(new ServiceReferenceNode(sr, true));
+                               }
+                       }
+               }
+
+       }
+
+       Bundle getBundle() {
+               return bundle;
+       }
+}
\ No newline at end of file
index 68e7d54df2cd65add7ffa72448142dd9021f4368..5ebd737912b993b6b48f7a4c9c072dcab953b594 100644 (file)
@@ -29,20 +29,15 @@ import org.eclipse.jface.viewers.TableViewer;
 import org.eclipse.jface.viewers.TableViewerColumn;
 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.Constants;
 
 /**
  * Overview of the bundles as a table. Equivalent to Equinox 'ss' console
  * command.
  */
-
-// public class BundlesView {}
-
 public class BundlesView extends ViewPart {
        private TableViewer viewer;
 
@@ -85,7 +80,7 @@ public class BundlesView extends ViewPart {
 
                // Symbolic name
                column = new TableViewerColumn(viewer, SWT.NONE);
-               column.getColumn().setWidth(300);
+               column.getColumn().setWidth(250);
                column.getColumn().setText("Symbolic Name");
                column.setLabelProvider(new ColumnLabelProvider() {
                        private static final long serialVersionUID = -4280840684440451080L;
@@ -149,68 +144,4 @@ public class BundlesView extends ViewPart {
                }
 
        }
-
-       /** Label provider for the state column */
-       private static class StateLabelProvider extends ColumnLabelProvider {
-               private static final long serialVersionUID = -7885583135316000733L;
-
-               @Override
-               public Image getImage(Object element) {
-                       Integer state = ((Bundle) element).getState();
-                       switch (state) {
-                       case Bundle.UNINSTALLED:
-                               return OsgiExplorerImages.INSTALLED;
-                       case Bundle.INSTALLED:
-                               return OsgiExplorerImages.INSTALLED;
-                       case Bundle.RESOLVED:
-                               return OsgiExplorerImages.RESOLVED;
-                       case Bundle.STARTING:
-                               return OsgiExplorerImages.STARTING;
-                       case Bundle.STOPPING:
-                               return OsgiExplorerImages.STARTING;
-                       case Bundle.ACTIVE:
-                               return OsgiExplorerImages.ACTIVE;
-                       default:
-                               return null;
-                       }
-               }
-
-               @Override
-               public String getText(Object element) {
-                       return null;
-               }
-
-               @Override
-               public String getToolTipText(Object element) {
-                       Bundle bundle = (Bundle) element;
-                       Integer state = bundle.getState();
-                       switch (state) {
-                       case Bundle.UNINSTALLED:
-                               return "UNINSTALLED";
-                       case Bundle.INSTALLED:
-                               return "INSTALLED";
-                       case Bundle.RESOLVED:
-                               return "RESOLVED";
-                       case Bundle.STARTING:
-                               String activationPolicy = bundle.getHeaders()
-                                               .get(Constants.BUNDLE_ACTIVATIONPOLICY).toString();
-
-                               // .get("Bundle-ActivationPolicy").toString();
-                               // FIXME constant triggers the compilation failure
-                               if (activationPolicy != null 
-                                               && activationPolicy.equals(Constants.ACTIVATION_LAZY))
-                                       // && activationPolicy.equals("lazy"))
-                                       // FIXME constant triggers the compilation failure
-                                       // && activationPolicy.equals(Constants.ACTIVATION_LAZY))
-                                       return "<<LAZY>>";
-                               return "STARTING";
-                       case Bundle.STOPPING:
-                               return "STOPPING";
-                       case Bundle.ACTIVE:
-                               return "ACTIVE";
-                       default:
-                               return null;
-                       }
-               }
-       }
 }
\ No newline at end of file
index b0d6b644aa2801f8be5772207c9ff2b9a1fbb4a7..5e4e3a2b887bfccfde0231179f5cc9332ee050df 100644 (file)
  */
 package org.argeo.eclipse.ui.workbench.osgi;
 
-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 java.util.ArrayList;
+import java.util.List;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.argeo.eclipse.ui.TreeParent;
 import org.argeo.eclipse.ui.workbench.WorkbenchUiPlugin;
-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;
 
-/** <b>Experimental</b> The OSGi runtime from a module perspective. */
+/** 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<ExportedPackage> exportedPackageComparator = new Comparator<ExportedPackage>() {
-
-               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);
@@ -74,6 +48,7 @@ public class ModulesView extends ViewPart {
        }
 
        private class ModulesContentProvider implements ITreeContentProvider {
+               private static final long serialVersionUID = 3819934804640641721L;
 
                public Object[] getElements(Object inputElement) {
                        return getChildren(inputElement);
@@ -84,77 +59,12 @@ public class ModulesView extends ViewPart {
                                BundleContext bundleContext = (BundleContext) parentElement;
                                Bundle[] bundles = bundleContext.getBundles();
 
-                               TreeParent bundlesNode = new TreeParent("Bundles");
+                               List<BundleNode> modules = new ArrayList<BundleNode>();
                                for (Bundle bundle : bundles) {
                                        if (bundle.getState() == Bundle.ACTIVE)
-                                               bundlesNode.addChild(new BundleNode(bundle));
+                                               modules.add(new BundleNode(bundle, true));
                                }
-
-                               // 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<Bundle, Set<ExportedPackage>> importedPackages = new HashMap<Bundle, Set<ExportedPackage>>();
-                               Map<String, Set<ExportedPackage>> packages = new TreeMap<String, Set<ExportedPackage>>();
-                               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<ExportedPackage>(
-                                                                                               exportedPackageComparator));
-                                                       Set<ExportedPackage> expPackages = (Set<ExportedPackage>) 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<ExportedPackage>(
-                                                                                                                               exportedPackageComparator));
-                                                                       Set<ExportedPackage> impPackages = (Set<ExportedPackage>) importedPackages
-                                                                                       .get(b);
-                                                                       impPackages.add(pkg);
-                                                               }
-                                                       }
-                                               }
-                               }
-
-                               TreeParent mPackageNode = new TreeParent("Multiple Packages");
-                               // TreeParent aPackageNode = new TreeParent("All Packages");
-                               for (String packageName : packages.keySet()) {
-                                       Set<ExportedPackage> 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
-                                                                                                                                       // };
+                               return modules.toArray();
                        } else if (parentElement instanceof TreeParent) {
                                return ((TreeParent) parentElement).getChildren();
                        } else {
@@ -175,205 +85,22 @@ public class ModulesView extends ViewPart {
                }
 
                public void dispose() {
-                       // TODO Auto-generated method stub
-
                }
 
                public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-                       // TODO Auto-generated method stub
-
-               }
-
-       }
-
-       protected Map<String, ExportedPackage> dependencySpace(Bundle bundle,
-                       Map<Bundle, Set<ExportedPackage>> importedPackages,
-                       Map<String, Set<String>> traces) {
-               log.debug("Dependency space for " + bundle.getSymbolicName());
-               Map<String, ExportedPackage> space = new TreeMap<String, ExportedPackage>();
-               fillDependencySpace(space, bundle, importedPackages,
-                               bundle.getSymbolicName(), traces);
-               return space;
-       }
-
-       /** Recursive */
-       protected void fillDependencySpace(Map<String, ExportedPackage> space,
-                       Bundle bundle, Map<Bundle, Set<ExportedPackage>> importedPackages,
-                       String currTrace, Map<String, Set<String>> traces) {
-               if (importedPackages.containsKey(bundle)) {
-                       Set<ExportedPackage> 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<String>());
-                               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<ExportedPackage> exportedPackages;
+       private class ModulesLabelProvider extends StateLabelProvider {
+               private static final long serialVersionUID = 5290046145534824722L;
 
-               public MultiplePackagesNode(String packageName,
-                               Set<ExportedPackage> 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<String, Bundle> bundles = new TreeMap<String, Bundle>();
-                       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<String, Bundle> bundles = new TreeMap<String, Bundle>();
-               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));
-                       }
+               @Override
+               public String getText(Object element) {
+                       if (element instanceof BundleNode)
+                               return element.toString() + " ["
+                                               + ((BundleNode) element).getBundle().getBundleId()
+                                               + "]";
+                       return element.toString();
                }
        }
 }
diff --git a/org.argeo.eclipse.ui.workbench/src/org/argeo/eclipse/ui/workbench/osgi/MultiplePackagesView.java b/org.argeo.eclipse.ui.workbench/src/org/argeo/eclipse/ui/workbench/osgi/MultiplePackagesView.java
new file mode 100644 (file)
index 0000000..8333825
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed 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.
+ */
+package org.argeo.eclipse.ui.workbench.osgi;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.eclipse.ui.workbench.WorkbenchUiPlugin;
+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.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;
+
+/** <b>Experimental</b> The OSGi runtime from a module perspective. */
+@SuppressWarnings({ "deprecation", "rawtypes", "unchecked" })
+public class MultiplePackagesView extends ViewPart {
+       private TreeViewer viewer;
+       private PackageAdmin packageAdmin;
+       private Comparator<ExportedPackage> epc = new Comparator<ExportedPackage>() {
+               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 LabelProvider());
+               viewer.setInput(WorkbenchUiPlugin.getDefault().getBundle()
+                               .getBundleContext());
+       }
+
+       @Override
+       public void setFocus() {
+               viewer.getTree().setFocus();
+       }
+
+       private class ModulesContentProvider implements ITreeContentProvider {
+               private static final long serialVersionUID = 3819934804640641721L;
+
+               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();
+
+                               // scan packages
+                               ServiceReference paSr = bundleContext
+                                               .getServiceReference(PackageAdmin.class.getName());
+                               // TODO: make a cleaner referencing
+                               packageAdmin = (PackageAdmin) bundleContext.getService(paSr);
+
+                               Map<Bundle, Set<ExportedPackage>> imported = new HashMap<Bundle, Set<ExportedPackage>>();
+                               Map<String, Set<ExportedPackage>> packages = new TreeMap<String, Set<ExportedPackage>>();
+                               for (Bundle bundle : bundles) {
+                                       processBundle(bundle, imported, packages);
+                               }
+
+                               List<MultiplePackagesNode> multiplePackages = new ArrayList<MultiplePackagesNode>();
+                               for (String packageName : packages.keySet()) {
+                                       Set<ExportedPackage> pkgs = packages.get(packageName);
+                                       if (pkgs.size() > 1) {
+                                               MultiplePackagesNode mpn = new MultiplePackagesNode(
+                                                               packageName, pkgs);
+                                               multiplePackages.add(mpn);
+                                       }
+                               }
+
+                               return multiplePackages.toArray();
+                       } else if (parentElement instanceof TreeParent) {
+                               return ((TreeParent) parentElement).getChildren();
+                       } else {
+                               return null;
+                       }
+               }
+
+               protected void processBundle(Bundle bundle,
+                               Map<Bundle, Set<ExportedPackage>> imported,
+                               Map<String, Set<ExportedPackage>> packages) {
+                       ExportedPackage[] pkgs = packageAdmin.getExportedPackages(bundle);
+                       if (pkgs == null)
+                               return;
+                       for (ExportedPackage pkg : pkgs) {
+                               if (!packages.containsKey(pkg.getName()))
+                                       packages.put(pkg.getName(), new TreeSet<ExportedPackage>(
+                                                       epc));
+                               Set<ExportedPackage> expPackages = packages.get(pkg.getName());
+                               expPackages.add(pkg);
+
+                               // imported
+                               for (Bundle b : pkg.getImportingBundles()) {
+                                       if (bundle.getBundleId() != b.getBundleId()) {
+                                               if (!imported.containsKey(b)) {
+                                                       imported.put(b, new TreeSet<ExportedPackage>(epc));
+                                               }
+                                               Set<ExportedPackage> impPackages = imported.get(b);
+                                               impPackages.add(pkg);
+                                       }
+                               }
+                       }
+               }
+
+               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() {
+               }
+
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+               }
+       }
+
+       private class MultiplePackagesNode extends TreeParent {
+               public MultiplePackagesNode(String packageName,
+                               Set<ExportedPackage> exportedPackages) {
+                       super(packageName);
+                       for (ExportedPackage pkg : exportedPackages) {
+                               addChild(new ExportedPackageNode(pkg));
+                       }
+               }
+       }
+
+       private class ExportedPackageNode extends TreeParent {
+               public ExportedPackageNode(ExportedPackage exportedPackage) {
+                       super(exportedPackage.getName() + " - "
+                                       + exportedPackage.getVersion() + " ("
+                                       + exportedPackage.getExportingBundle() + ")");
+                       for (Bundle bundle : exportedPackage.getImportingBundles()) {
+                               addChild(new BundleNode(bundle, true));
+                       }
+               }
+       }
+}
index 64a240c59f7ea8f7e17417d13f0726f2995bf11e..7f58ed0e2441462e3f567837157e320dafa20140 100644 (file)
@@ -20,12 +20,16 @@ import org.eclipse.swt.graphics.Image;
 
 /** Shared icons. */
 public class OsgiExplorerImages {
-       public final static Image INSTALLED = WorkbenchUiPlugin
-                       .getImageDescriptor("icons/installed.gif").createImage();
+       public final static Image INSTALLED = WorkbenchUiPlugin.getImageDescriptor(
+                       "icons/installed.gif").createImage();
        public final static Image RESOLVED = WorkbenchUiPlugin.getImageDescriptor(
                        "icons/resolved.gif").createImage();
        public final static Image STARTING = WorkbenchUiPlugin.getImageDescriptor(
                        "icons/starting.gif").createImage();
        public final static Image ACTIVE = WorkbenchUiPlugin.getImageDescriptor(
                        "icons/active.gif").createImage();
+       public final static Image SERVICE_PUBLISHED = WorkbenchUiPlugin
+                       .getImageDescriptor("icons/service_published.gif").createImage();
+       public final static Image SERVICE_REFERENCED = WorkbenchUiPlugin
+                       .getImageDescriptor("icons/service_referenced.gif").createImage();
 }
diff --git a/org.argeo.eclipse.ui.workbench/src/org/argeo/eclipse/ui/workbench/osgi/ServiceReferenceNode.java b/org.argeo.eclipse.ui.workbench/src/org/argeo/eclipse/ui/workbench/osgi/ServiceReferenceNode.java
new file mode 100644 (file)
index 0000000..0da5287
--- /dev/null
@@ -0,0 +1,46 @@
+package org.argeo.eclipse.ui.workbench.osgi;
+
+import org.argeo.eclipse.ui.TreeParent;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+
+/** A tree element representing a {@link ServiceReference} */
+@SuppressWarnings({ "rawtypes" })
+class ServiceReferenceNode extends TreeParent {
+       private final ServiceReference serviceReference;
+       private final boolean published;
+
+       public ServiceReferenceNode(ServiceReference serviceReference,
+                       boolean published) {
+               super(serviceReference.toString());
+               this.serviceReference = serviceReference;
+               this.published = published;
+
+               if (isPublished()) {
+                       Bundle[] usedBundles = serviceReference.getUsingBundles();
+                       if (usedBundles != null) {
+                               for (Bundle b : usedBundles) {
+                                       if (b != null)
+                                               addChild(new BundleNode(b));
+                               }
+                       }
+               } else {
+                       Bundle provider = serviceReference.getBundle();
+                       addChild(new BundleNode(provider));
+               }
+
+               for (String key : serviceReference.getPropertyKeys()) {
+                       addChild(new TreeParent(key + "="
+                                       + serviceReference.getProperty(key)));
+               }
+
+       }
+
+       public ServiceReference getServiceReference() {
+               return serviceReference;
+       }
+
+       public boolean isPublished() {
+               return published;
+       }
+}
diff --git a/org.argeo.eclipse.ui.workbench/src/org/argeo/eclipse/ui/workbench/osgi/StateLabelProvider.java b/org.argeo.eclipse.ui.workbench/src/org/argeo/eclipse/ui/workbench/osgi/StateLabelProvider.java
new file mode 100644 (file)
index 0000000..803a358
--- /dev/null
@@ -0,0 +1,82 @@
+package org.argeo.eclipse.ui.workbench.osgi;
+
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.swt.graphics.Image;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+
+/** Label provider showing the sate of bundles */
+class StateLabelProvider extends ColumnLabelProvider {
+       private static final long serialVersionUID = -7885583135316000733L;
+
+       @Override
+       public Image getImage(Object element) {
+               int state;
+               if (element instanceof Bundle)
+                       state = ((Bundle) element).getState();
+               else if (element instanceof BundleNode)
+                       state = ((BundleNode) element).getBundle().getState();
+               else if (element instanceof ServiceReferenceNode)
+                       if (((ServiceReferenceNode) element).isPublished())
+                               return OsgiExplorerImages.SERVICE_PUBLISHED;
+                       else
+                               return OsgiExplorerImages.SERVICE_REFERENCED;
+               else
+                       return null;
+
+               switch (state) {
+               case Bundle.UNINSTALLED:
+                       return OsgiExplorerImages.INSTALLED;
+               case Bundle.INSTALLED:
+                       return OsgiExplorerImages.INSTALLED;
+               case Bundle.RESOLVED:
+                       return OsgiExplorerImages.RESOLVED;
+               case Bundle.STARTING:
+                       return OsgiExplorerImages.STARTING;
+               case Bundle.STOPPING:
+                       return OsgiExplorerImages.STARTING;
+               case Bundle.ACTIVE:
+                       return OsgiExplorerImages.ACTIVE;
+               default:
+                       return null;
+               }
+       }
+
+       @Override
+       public String getText(Object element) {
+               return null;
+       }
+
+       @Override
+       public String getToolTipText(Object element) {
+               Bundle bundle = (Bundle) element;
+               Integer state = bundle.getState();
+               switch (state) {
+               case Bundle.UNINSTALLED:
+                       return "UNINSTALLED";
+               case Bundle.INSTALLED:
+                       return "INSTALLED";
+               case Bundle.RESOLVED:
+                       return "RESOLVED";
+               case Bundle.STARTING:
+                       String activationPolicy = bundle.getHeaders()
+                                       .get(Constants.BUNDLE_ACTIVATIONPOLICY).toString();
+
+                       // .get("Bundle-ActivationPolicy").toString();
+                       // FIXME constant triggers the compilation failure
+                       if (activationPolicy != null
+                                       && activationPolicy.equals(Constants.ACTIVATION_LAZY))
+                               // && activationPolicy.equals("lazy"))
+                               // FIXME constant triggers the compilation failure
+                               // && activationPolicy.equals(Constants.ACTIVATION_LAZY))
+                               return "<<LAZY>>";
+                       return "STARTING";
+               case Bundle.STOPPING:
+                       return "STOPPING";
+               case Bundle.ACTIVE:
+                       return "ACTIVE";
+               default:
+                       return null;
+               }
+       }
+}
\ No newline at end of file