Add two bundle related utility methods

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@667258 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/Util.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/Util.java
index 67972dc..02237f5 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/Util.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/Util.java
@@ -20,11 +20,15 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintWriter;
-import java.util.Collection;
+import java.util.Arrays;
+import java.util.Comparator;
 
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.commons.io.IOUtils;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
 
 
 /**
@@ -90,4 +94,102 @@
     {
         return Util.class.getResourceAsStream( resource );
     }
+
+
+    /**
+     * Return a display name for the given <code>bundle</code>:
+     * <ol>
+     * <li>If the bundle has a non-empty <code>Bundle-Name</code> manifest
+     * header that value is returned.</li>
+     * <li>Otherwise the symbolic name is returned if set</li>
+     * <li>Otherwise the bundle's location is returned if defined</li>
+     * <li>Finally, as a last ressort, the bundles id is returned</li>
+     * </ol>
+     */
+    public static String getName( Bundle bundle )
+    {
+        String name = ( String ) bundle.getHeaders().get( Constants.BUNDLE_NAME );
+        if ( name == null || name.length() == 0 )
+        {
+            name = bundle.getSymbolicName();
+            if ( name == null )
+            {
+                name = bundle.getLocation();
+                if ( name == null )
+                {
+                    name = String.valueOf( bundle.getBundleId() );
+                }
+            }
+        }
+        return name;
+    }
+
+
+    /**
+     * Orders the bundles according to their name as returned by
+     * {@link #getName(Bundle)}, with the exception that the system bundle is
+     * always place as the first entry. If two bundles have the same name, they
+     * are ordered according to their version. If they have the same version,
+     * the bundle with the lower bundle id comes before the other.
+     */
+    public static void sort( Bundle[] bundles )
+    {
+        Arrays.sort( bundles, BUNDLE_NAME_COMPARATOR );
+    }
+
+    // ---------- inner classes ------------------------------------------------
+
+    private static final Comparator BUNDLE_NAME_COMPARATOR = new Comparator()
+    {
+        public int compare( Object o1, Object o2 )
+        {
+            return compare( ( Bundle ) o1, ( Bundle ) o2 );
+        }
+
+
+        public int compare( Bundle b1, Bundle b2 )
+        {
+
+            // the same bundles
+            if ( b1 == b2 || b1.getBundleId() == b2.getBundleId() )
+            {
+                return 0;
+            }
+
+            // special case for system bundle, which always is first
+            if ( b1.getBundleId() == 0 )
+            {
+                return -1;
+            }
+            else if ( b2.getBundleId() == 0 )
+            {
+                return 1;
+            }
+
+            // compare the symbolic names
+            int snComp = Util.getName( b1 ).compareToIgnoreCase( Util.getName( b2 ) );
+            if ( snComp != 0 )
+            {
+                return snComp;
+            }
+
+            // same names, compare versions
+            Version v1 = Version.parseVersion( ( String ) b1.getHeaders().get( Constants.BUNDLE_VERSION ) );
+            Version v2 = Version.parseVersion( ( String ) b2.getHeaders().get( Constants.BUNDLE_VERSION ) );
+            int vComp = v1.compareTo( v2 );
+            if ( vComp != 0 )
+            {
+                return vComp;
+            }
+
+            // same version ? Not really, but then, we compare by bundle id
+            if ( b1.getBundleId() < b2.getBundleId() )
+            {
+                return -1;
+            }
+
+            // b1 id must be > b2 id because equality is already checked
+            return 1;
+        }
+    };
 }