FELIX-3025 : Add a configuration status list with a short bundle list

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1146584 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/BundlesConfigurationPrinter.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/BundlesConfigurationPrinter.java
new file mode 100644
index 0000000..d1abb70
--- /dev/null
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/BundlesConfigurationPrinter.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.felix.webconsole.internal.core;
+
+
+import java.io.PrintWriter;
+import java.text.MessageFormat;
+import java.util.*;
+
+import org.apache.felix.webconsole.internal.AbstractConfigurationPrinter;
+import org.osgi.framework.*;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+
+
+/**
+ * The <code>BundlesConfigurationPrinter</code> prints out the bundle list.
+ */
+public class BundlesConfigurationPrinter
+    extends AbstractConfigurationPrinter
+{
+
+    private ServiceTracker packageAdminTracker;
+
+    /**
+     * @see org.apache.felix.webconsole.internal.AbstractConfigurationPrinter#activate(org.osgi.framework.BundleContext)
+     */
+    public void activate(final BundleContext bundleContext)
+    {
+        super.activate(bundleContext);
+        this.packageAdminTracker = new ServiceTracker(bundleContext, PackageAdmin.class.getName(), null);
+        this.packageAdminTracker.open();
+    }
+
+    /**
+     * @see org.apache.felix.webconsole.internal.AbstractConfigurationPrinter#deactivate()
+     */
+    public void deactivate()
+    {
+        if ( this.packageAdminTracker != null )
+        {
+            this.packageAdminTracker.close();
+            this.packageAdminTracker = null;
+        }
+        super.deactivate();
+    }
+
+    /**
+     * @see org.apache.felix.webconsole.ConfigurationPrinter#getTitle()
+     */
+    public String getTitle()
+    {
+        return "Bundlelist";
+    }
+
+    private String getHeaderValue(final Bundle b, final String name)
+    {
+        String val = (String)b.getHeaders().get(name);
+        if ( val == null )
+        {
+            val = "";
+        }
+        return val;
+    }
+
+    private String getState(final int state)
+    {
+        switch (state)
+        {
+            case Bundle.ACTIVE : return "active";
+            case Bundle.INSTALLED : return "installed";
+            case Bundle.RESOLVED : return "resolved";
+            case Bundle.STARTING : return "starting";
+            case Bundle.STOPPING : return "stopping";
+            case Bundle.UNINSTALLED : return "uninstalled";
+        }
+        return String.valueOf(state);
+    }
+
+    private final boolean isFragmentBundle( final Bundle bundle)
+    {
+        return ((PackageAdmin)this.packageAdminTracker.getService()).getBundleType( bundle ) == PackageAdmin.BUNDLE_TYPE_FRAGMENT;
+    }
+
+    /**
+     * @see org.apache.felix.webconsole.ConfigurationPrinter#printConfiguration(java.io.PrintWriter)
+     */
+    public void printConfiguration( final PrintWriter pw )
+    {
+        final Bundle[] bundles = this.getBundleContext().getBundles();
+        // create a map for sorting first
+        final TreeMap bundlesMap = new TreeMap();
+        int active = 0, installed = 0, resolved = 0, fragments = 0;
+        for( int i =0; i<bundles.length; i++)
+        {
+            final Bundle bundle = bundles[i];
+            final String symbolicName = bundle.getSymbolicName();
+            final String version = (String)bundle.getHeaders().get(Constants.BUNDLE_VERSION);
+
+            // count states and calculate prefix
+            switch ( bundle.getState() )
+            {
+                case Bundle.ACTIVE:
+                    active++;
+                    break;
+                case Bundle.INSTALLED:
+                    installed++;
+                    break;
+                case Bundle.RESOLVED:
+                    if ( isFragmentBundle( bundle ) )
+                    {
+                        fragments++;
+                    }
+                    else
+                    {
+                        resolved++;
+                    }
+                    break;
+            }
+
+            final String key = symbolicName + ':' + version;
+            final String value = MessageFormat.format( "{0} ({1}) \"{2}\" [{3}, {4}] {5}", new Object[]
+                  { symbolicName,
+                    version,
+                    getHeaderValue(bundle, Constants.BUNDLE_NAME),
+                    getState(bundle.getState()),
+                    String.valueOf(bundle.getBundleId()),
+                    isFragmentBundle(bundle) ? "(fragment)" : ""} );
+            bundlesMap.put(key, value);
+
+        }
+        final StringBuffer buffer = new StringBuffer();
+        buffer.append("Bundlelist: ");
+        appendBundleInfoCount(buffer, "in total", bundles.length);
+        if ( active == bundles.length || active + fragments == bundles.length )
+        {
+            buffer.append(" - all ");
+            appendBundleInfoCount(buffer, "active.", bundles.length);
+        }
+        else
+        {
+            if ( active != 0 )
+            {
+                buffer.append(", ");
+                appendBundleInfoCount(buffer, "active", active);
+            }
+            if ( fragments != 0 )
+            {
+                buffer.append(", ");
+                appendBundleInfoCount(buffer, "active fragments", fragments);
+            }
+            if ( resolved != 0 )
+            {
+                buffer.append(", ");
+                appendBundleInfoCount(buffer, "resolved", resolved);
+            }
+            if ( installed != 0 )
+            {
+                buffer.append(", ");
+                appendBundleInfoCount(buffer, "installed", installed);
+            }
+        }
+        pw.println(buffer.toString());
+        pw.println("-----------------------------------------------------------------------------");
+        final Iterator i = bundlesMap.entrySet().iterator();
+        while ( i.hasNext() )
+        {
+            final Map.Entry entry = (Map.Entry)i.next();
+            pw.println(entry.getValue());
+
+        }
+    }
+
+    private void appendBundleInfoCount( final StringBuffer buf, String msg, int count )
+    {
+        buf.append(count);
+        buf.append(" bundle");
+        if ( count != 1 )
+            buf.append( 's' );
+        buf.append(' ');
+        buf.append(msg);
+    }
+}
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
index 0c5c5f5..b7a9cf1 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
@@ -20,33 +20,13 @@
 import java.io.IOException;
 import java.net.URL;
 import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.ResourceBundle;
-import java.util.Set;
-import javax.servlet.GenericServlet;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-import javax.servlet.http.HttpServletResponse;
+import java.util.*;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
 
 import org.apache.commons.io.FilenameUtils;
-import org.apache.felix.webconsole.AbstractWebConsolePlugin;
-import org.apache.felix.webconsole.BrandingPlugin;
-import org.apache.felix.webconsole.WebConsoleConstants;
-import org.apache.felix.webconsole.WebConsoleSecurityProvider;
+import org.apache.felix.webconsole.*;
 import org.apache.felix.webconsole.internal.OsgiManagerPlugin;
 import org.apache.felix.webconsole.internal.Util;
 import org.apache.felix.webconsole.internal.core.BundlesServlet;
@@ -54,13 +34,8 @@
 import org.apache.felix.webconsole.internal.i18n.ResourceBundleManager;
 import org.apache.felix.webconsole.internal.misc.ConfigurationRender;
 import org.apache.felix.webconsole.internal.servlet.PluginHolder.InternalPlugin;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
+import org.osgi.framework.*;
 import org.osgi.framework.Filter;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.http.HttpContext;
 import org.osgi.service.http.HttpService;
 import org.osgi.service.log.LogService;
@@ -151,6 +126,7 @@
             "org.apache.felix.webconsole.internal.compendium.ConfigurationAdminConfigurationPrinter",
             "org.apache.felix.webconsole.internal.compendium.PreferencesConfigurationPrinter",
             "org.apache.felix.webconsole.internal.compendium.WireAdminConfigurationPrinter",
+            "org.apache.felix.webconsole.internal.core.BundlesConfigurationPrinter",
             "org.apache.felix.webconsole.internal.core.PermissionsConfigurationPrinter",
             "org.apache.felix.webconsole.internal.core.ServicesConfigurationPrinter",
             "org.apache.felix.webconsole.internal.misc.SystemPropertiesPrinter",
@@ -938,7 +914,7 @@
      * Returns <code>true</code> if the list of enabled plugins is
      * configured but the plugin is not contained in that list.
      * <p>
-     * This method is intended to be used only for {@link InternalPlugin#isEnabled()} 
+     * This method is intended to be used only for {@link InternalPlugin#isEnabled()}
      */
     boolean isPluginDisabled( String pluginClass )
     {