You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2008/01/18 11:03:37 UTC

svn commit: r613118 - in /incubator/sling/trunk/osgi/console-web: pom.xml src/main/java/org/apache/sling/osgi/console/web/internal/AjaxBundleDetailsAction.java

Author: fmeschbe
Date: Fri Jan 18 02:03:37 2008
New Revision: 613118

URL: http://svn.apache.org/viewvc?rev=613118&view=rev
Log:
SLING-151 List imports and exports of unresolved (installed, that is) bundles
to provide some help in resolving why a bundle might not resolve. Specifically
each import is analzyed:

   * If the import can be satisifed, print the potential provider
   * If the import cannot be satisifed but is part of the bundle,
       ignore the import (not actually correct, should look at
       export list, but sounds enough)
   * If an import is listed in the bootdelegation property and
       cannot be resolved, both situations are marked.

Modified:
    incubator/sling/trunk/osgi/console-web/pom.xml
    incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/AjaxBundleDetailsAction.java

Modified: incubator/sling/trunk/osgi/console-web/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/osgi/console-web/pom.xml?rev=613118&r1=613117&r2=613118&view=diff
==============================================================================
--- incubator/sling/trunk/osgi/console-web/pom.xml (original)
+++ incubator/sling/trunk/osgi/console-web/pom.xml Fri Jan 18 02:03:37 2008
@@ -70,10 +70,13 @@
                             <!-- Required by FileUpload and Util -->
                             org.apache.commons.io,
                             org.apache.commons.io.filefilter,
-                            org.apache.commons.io.output
+                            org.apache.commons.io.output,
+
+                            <!-- Import/Export-Package parsing -->
+                            org.apache.felix.bundlerepository
                         </Private-Package>
                         <Import-Package>
-                            org.apache.felix.scr;resolution:=optional,*
+                            org.apache.felix.*;resolution:=optional,*
                         </Import-Package>
                     </instructions>
                 </configuration>
@@ -129,5 +132,12 @@
                 </exclusion>
             </exclusions>
         </dependency>
+
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.bundlerepository</artifactId>
+            <scope>compile</scope>
+        </dependency>
+
     </dependencies>
 </project>

Modified: incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/AjaxBundleDetailsAction.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/AjaxBundleDetailsAction.java?rev=613118&r1=613117&r2=613118&view=diff
==============================================================================
--- incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/AjaxBundleDetailsAction.java (original)
+++ incubator/sling/trunk/osgi/console-web/src/main/java/org/apache/sling/osgi/console/web/internal/AjaxBundleDetailsAction.java Fri Jan 18 02:03:37 2008
@@ -22,19 +22,27 @@
 import java.util.Comparator;
 import java.util.Date;
 import java.util.Dictionary;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.StringTokenizer;
+import java.util.TreeMap;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.felix.bundlerepository.R4Attribute;
+import org.apache.felix.bundlerepository.R4Export;
+import org.apache.felix.bundlerepository.R4Import;
+import org.apache.felix.bundlerepository.R4Package;
 import org.apache.sling.commons.json.JSONArray;
 import org.apache.sling.commons.json.JSONException;
 import org.apache.sling.commons.json.JSONObject;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
 import org.osgi.service.cm.ConfigurationAdmin;
 import org.osgi.service.component.ComponentConstants;
 import org.osgi.service.component.ComponentContext;
@@ -107,7 +115,11 @@
 
                 keyVal(props, "Start Level", getStartLevel(bundle));
 
-                listImportExport(props, bundle);
+                if (bundle.getState() == Bundle.INSTALLED) {
+                    listImportExportsUnresolved(props, bundle);
+                } else {
+                    listImportExport(props, bundle);
+                }
 
                 listServices(props, bundle);
 
@@ -147,21 +159,7 @@
 
             StringBuffer val = new StringBuffer();
             for (ExportedPackage export : exports) {
-
-                boolean bootDel = isBootDelegated(export.getName());
-                if (bootDel) {
-                    val.append("<span style=\"color: red\">!! ");
-                }
-
-                val.append(export.getName());
-                val.append(",version=");
-                val.append(export.getVersion());
-
-                if (bootDel) {
-                    val.append(" -- Overwritten by Boot Delegation</span>");
-                }
-
-                val.append("<br />");
+                printExport(val, export.getName(), export.getVersion());
             }
             keyVal(props, "Exported Packages", val.toString());
         } else {
@@ -194,46 +192,92 @@
                 });
                 // and finally print out
                 for (ExportedPackage ep : packages) {
+                    printImport(val, ep.getName(), ep.getVersion(), ep);
+                }
+            } else {
+                // add description if there are no imports
+                val.append("None");
+            }
 
-                    boolean bootDel = isBootDelegated(ep.getName());
-                    if (bootDel) {
-                        val.append("<span style=\"color: red\">!! ");
-                    }
+            keyVal(props, "Imported Packages", val.toString());
+        }
+    }
 
-                    val.append(ep.getName());
-                    val.append(",version=").append(ep.getVersion());
-                    val.append(" from ");
-
-                    if (ep.getExportingBundle().getSymbolicName() != null) {
-                        // list the bundle name if not null
-                        val.append(ep.getExportingBundle().getSymbolicName());
-                        val.append(" (").append(
-                            ep.getExportingBundle().getBundleId());
-                        val.append(")");
-                    } else if (ep.getExportingBundle().getLocation() != null) {
-                        // otherwise try the location
-                        val.append(ep.getExportingBundle().getLocation());
-                        val.append(" (").append(
-                            ep.getExportingBundle().getBundleId());
-                        val.append(")");
-                    } else {
-                        // fallback to just the bundle id
-                        // only append the bundle
-                        val.append(ep.getExportingBundle().getBundleId());
-                    }
+    private void listImportExportsUnresolved(JSONArray props, Bundle bundle) {
+        Dictionary<?, ?> dict = bundle.getHeaders();
 
-                    if (bootDel) {
-                        val.append(" -- Overwritten by Boot Delegation</span>");
+        String target = (String) dict.get(Constants.EXPORT_PACKAGE);
+        if (target != null) {
+            R4Package[] pkgs = R4Package.parseImportOrExportHeader(target);
+            if (pkgs != null && pkgs.length > 0) {
+                // do alphabetical sort
+                Arrays.sort(pkgs, new Comparator<R4Package>() {
+                    public int compare(R4Package p1, R4Package p2) {
+                        return p1.getName().compareTo(p2.getName());
                     }
+                });
+
+                StringBuffer val = new StringBuffer();
+                for (R4Package pkg : pkgs) {
+                    R4Export export = new R4Export(pkg);
 
-                    val.append("<br />");
+                    printExport(val, export.getName(), export.getVersion());
                 }
+                keyVal(props, "Exported Packages", val.toString());
             } else {
-                // add description if there are no imports
-                val.append("None");
+                keyVal(props, "Exported Packages", "None");
             }
+        }
 
-            keyVal(props, "Imported Packages", val.toString());
+        target = (String) dict.get(Constants.IMPORT_PACKAGE);
+        if (target != null) {
+            R4Package[] pkgs = R4Package.parseImportOrExportHeader(target);
+            if (pkgs != null && pkgs.length > 0) {
+                Map<String, R4Import> imports = new TreeMap<String, R4Import>();
+                for (R4Package pkg : pkgs) {
+                    imports.put(pkg.getName(), new R4Import(pkg));
+                }
+
+                // collect import packages first
+                final Map<String, ExportedPackage> candidates = new HashMap<String, ExportedPackage>();
+                ExportedPackage[] exports = packageAdmin.getExportedPackages((Bundle) null);
+                if (exports != null && exports.length > 0) {
+
+                    for (int i = 0; i < exports.length; i++) {
+                        final ExportedPackage ep = exports[i];
+
+                        R4Import imp = imports.get(ep.getName());
+                        if (imp != null && imp.isSatisfied(toR4Export(ep))) {
+                            candidates.put(ep.getName(), ep);
+                        }
+                    }
+                }
+
+                // now sort
+                StringBuffer val = new StringBuffer();
+                if (imports.size() > 0) {
+                    for (R4Import r4Import : imports.values()) {
+                        ExportedPackage ep = candidates.get(r4Import.getName());
+
+                        // if there is no matching export, check whether this
+                        // bundle has the package, ignore the entry in this case
+                        if (ep == null) {
+                            String path = r4Import.getName().replace('.', '/');
+                            if (bundle.getResource(path) != null) {
+                                continue;
+                            }
+                        }
+
+                        printImport(val, r4Import.getName(),
+                            r4Import.getVersion(), ep);
+                    }
+                } else {
+                    // add description if there are no imports
+                    val.append("None");
+                }
+
+                keyVal(props, "Imported Packages", val.toString());
+            }
         }
     }
 
@@ -297,6 +341,68 @@
         }
     }
 
+    private void printExport(StringBuffer val, String name, Version version) {
+        boolean bootDel = isBootDelegated(name);
+        if (bootDel) {
+            val.append("<span style=\"color: red\">!! ");
+        }
+
+        val.append(name);
+        val.append(",version=");
+        val.append(version);
+
+        if (bootDel) {
+            val.append(" -- Overwritten by Boot Delegation</span>");
+        }
+
+        val.append("<br />");
+
+    }
+
+    private void printImport(StringBuffer val, String name, Version version,
+            ExportedPackage export) {
+        boolean bootDel = isBootDelegated(name);
+        if (bootDel || export == null) {
+            val.append("<span style=\"color: red\">!! ");
+        }
+
+        val.append(name);
+        val.append(",version=").append(version);
+        val.append(" from ");
+
+        if (export != null) {
+            if (export.getExportingBundle().getSymbolicName() != null) {
+                // list the bundle name if not null
+                val.append(export.getExportingBundle().getSymbolicName());
+                val.append(" (").append(
+                    export.getExportingBundle().getBundleId());
+                val.append(")");
+            } else if (export.getExportingBundle().getLocation() != null) {
+                // otherwise try the location
+                val.append(export.getExportingBundle().getLocation());
+                val.append(" (").append(
+                    export.getExportingBundle().getBundleId());
+                val.append(")");
+            } else {
+                // fallback to just the bundle id
+                // only append the bundle
+                val.append(export.getExportingBundle().getBundleId());
+            }
+
+            if (bootDel) {
+                val.append(" -- Overwritten by Boot Delegation</span>");
+            }
+        } else {
+            val.append(" -- Cannot be resolved");
+            if (bootDel) {
+                val.append(" and overwritten by Boot Delegation");
+            }
+            val.append("</span>");
+        }
+
+        val.append("<br />");
+    }
+
     // returns true if the package is listed in the bootdelegation property
     private boolean isBootDelegated(String pkgName) {
 
@@ -327,6 +433,13 @@
         }
 
         return false;
+    }
+
+    private R4Export toR4Export(ExportedPackage export) {
+        R4Attribute version = new R4Attribute(Constants.VERSION_ATTRIBUTE,
+            export.getVersion().toString(), false);
+        return new R4Export(export.getName(), null,
+            new R4Attribute[] { version });
     }
 
     // ---------- SCR integration ----------------------------------------------