FELIX-1230 - Use MetaTypeService to get all object class definitions for
singleton and factory configurations to be made available on the
configuration page.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@784089 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ConfigManager.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ConfigManager.java
index 9d7b1b8..f519ceb 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ConfigManager.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ConfigManager.java
@@ -17,9 +17,25 @@
 package org.apache.felix.webconsole.internal.compendium;
 
 
-import java.io.*;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
 import java.lang.reflect.Array;
-import java.util.*;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.Vector;
 import java.util.Map.Entry;
 
 import javax.servlet.ServletException;
@@ -28,9 +44,20 @@
 
 import org.apache.felix.webconsole.internal.Util;
 import org.apache.felix.webconsole.internal.servlet.OsgiManager;
-import org.json.*;
-import org.osgi.framework.*;
-import org.osgi.service.cm.*;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONWriter;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.cm.ManagedServiceFactory;
+import org.osgi.service.log.LogService;
 import org.osgi.service.metatype.AttributeDefinition;
 import org.osgi.service.metatype.ObjectClassDefinition;
 
@@ -346,6 +373,9 @@
         {
             // start with ManagedService instances
             SortedMap optionsPlain = getServices( ManagedService.class.getName(), pidFilter, locale, true );
+            
+            // next are the MetaType informations without ManagedService
+            addMetaTypeNames( optionsPlain, getPidObjectClasses( locale ), pidFilter, Constants.SERVICE_PID );
 
             // add in existing configuration (not duplicating ManagedServices)
             Configuration[] cfgs = ca.listConfigurations( pidFilter );
@@ -383,7 +413,7 @@
         }
         catch ( Exception e )
         {
-            // write a message or ignore
+            getLog().log( LogService.LOG_ERROR, "listConfigurations: Unexpected problem encountered", e );
         }
     }
 
@@ -394,11 +424,13 @@
         try
         {
             SortedMap optionsFactory = getServices( ManagedServiceFactory.class.getName(), pidFilter, locale, true );
+            addMetaTypeNames( optionsFactory, getFactoryPidObjectClasses( locale ), pidFilter,
+                ConfigurationAdmin.SERVICE_FACTORYPID );
             printOptionsForm( pw, optionsFactory, "configSelection_factory", "create", "Create" );
         }
         catch ( Exception e )
         {
-            // write a message or ignore
+            getLog().log( LogService.LOG_ERROR, "listFactoryConfigurations: Unexpected problem encountered", e );
         }
     }
 
@@ -439,6 +471,36 @@
     }
 
 
+    private void addMetaTypeNames( final Map pidMap, final Collection ocdCollection, final String filterSpec, final String type )
+    {
+        Filter filter = null;
+        if ( filterSpec != null )
+        {
+            try
+            {
+                filter = getBundleContext().createFilter( filterSpec );
+            }
+            catch ( InvalidSyntaxException not_expected )
+            {
+            }
+        }
+
+        for ( Iterator oci = ocdCollection.iterator(); oci.hasNext(); )
+        {
+            final ObjectClassDefinition ocd = ( ObjectClassDefinition ) oci.next();
+            final String pid = ocd.getID();
+            final Dictionary props = new Hashtable();
+            props.put( type, pid );
+            if ( filter == null || filter.match( props ) )
+            {
+                final String name = ocd.getName() + " (" + pid + ")";
+                pidMap.put( pid, name );
+            }
+        }
+
+    }
+
+
     private void printOptionsForm( PrintWriter pw, SortedMap options, String formId, String submitMethod,
         String submitLabel )
     {
@@ -725,7 +787,7 @@
             // only delete if the PID is not our place holder
             if ( !PLACEHOLDER_PID.equals( pid ) )
             {
-                // TODO: should log this here !!
+                getLog().log( LogService.LOG_INFO, "applyConfiguration: Deleting configuration " + pid );
                 Configuration config = ca.getConfiguration( pid, null );
                 config.delete();
             }
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ConfigManagerBase.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ConfigManagerBase.java
index 0aae6f4..b8e2548 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ConfigManagerBase.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ConfigManagerBase.java
@@ -17,6 +17,8 @@
 package org.apache.felix.webconsole.internal.compendium;
 
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
@@ -34,11 +36,16 @@
 
 
 /**
- * The <code>ConfigManagerBase</code> TODO
- * 
+ * The <code>ConfigManagerBase</code> is the base class for the
+ * ConfigurationAdmin support in the web console. It provides various helper
+ * methods mostly with respect to using the MetaTypeService to access
+ * configuration descriptiorns.
  */
 abstract class ConfigManagerBase extends BaseWebConsolePlugin
 {
+
+    private static final long serialVersionUID = -6691093960031418130L;
+
     private static final String CONFIGURATION_ADMIN_NAME = ConfigurationAdmin.class.getName();
 
     private static final String META_TYPE_NAME = MetaTypeService.class.getName();
@@ -52,32 +59,69 @@
 
     protected MetaTypeService getMetaTypeService()
     {
-        //TODO: 
         return ( MetaTypeService ) getService( META_TYPE_NAME );
     }
 
 
-    protected Map getMetadataPids()
+    /**
+     * Returns a map of PIDs and providing bundles of MetaType information. The
+     * map is indexed by PID and the value of each entry is the bundle providing
+     * the MetaType information for that PID.
+     */
+    protected Collection getPidObjectClasses( final String locale )
     {
-        Map pids = new HashMap();
-        MetaTypeService mts = this.getMetaTypeService();
+        return getObjectClasses( PID_GETTER, locale );
+    }
+
+
+    /**
+     * Returns a map of factory PIDs and providing bundles of MetaType
+     * information. The map is indexed by factory PID and the value of each
+     * entry is the bundle providing the MetaType information for that factory
+     * PID.
+     */
+    protected Collection getFactoryPidObjectClasses( final String locale )
+    {
+        return getObjectClasses( FACTORY_PID_GETTER, locale );
+    }
+
+
+    /**
+     * Returns the <code>ObjectClassDefinition</code> objects for the ids
+     * returned by the <code>idGetter</code>. Depending on the
+     * <code>idGetter</code> implementation this will be for factory PIDs or
+     * plain PIDs.
+     * 
+     * @param idGetter The {@link IdGetter} used to get the list of factory PIDs
+     *          or PIDs from <code>MetaTypeInformation</code> objetcs.
+     * @param locale The name of the locale to get the object class definitions
+     *          for.
+     */
+    private Collection getObjectClasses( final IdGetter idGetter, final String locale )
+    {
+        final Collection objectClasses = new ArrayList();
+        final MetaTypeService mts = this.getMetaTypeService();
         if ( mts != null )
         {
-            Bundle[] bundles = this.getBundleContext().getBundles();
+            final Bundle[] bundles = this.getBundleContext().getBundles();
             for ( int i = 0; i < bundles.length; i++ )
             {
-                MetaTypeInformation mti = mts.getMetaTypeInformation( bundles[i] );
+                final MetaTypeInformation mti = mts.getMetaTypeInformation( bundles[i] );
                 if ( mti != null )
                 {
-                    String[] pidList = mti.getPids();
-                    for ( int j = 0; pidList != null && j < pidList.length; j++ )
+                    final String[] idList = idGetter.getIds( mti );
+                    for ( int j = 0; idList != null && j < idList.length; j++ )
                     {
-                        pids.put( pidList[j], bundles[i] );
+                        ObjectClassDefinition ocd = mti.getObjectClassDefinition( idList[j], locale );
+                        if ( ocd != null )
+                        {
+                            objectClasses.add( ocd );
+                        }
                     }
                 }
             }
         }
-        return pids;
+        return objectClasses;
     }
 
 
@@ -221,4 +265,45 @@
         }
     }
 
+    /**
+     * The <code>IdGetter</code> interface is an internal helper to abstract
+     * retrieving object class definitions from all bundles for either
+     * pids or factory pids.
+     * 
+     * @see #PID_GETTER
+     * @see #FACTORY_PID_GETTER
+     */
+    private static interface IdGetter
+    {
+        String[] getIds( MetaTypeInformation metaTypeInformation );
+    }
+
+    /** 
+     * The implementation of the {@link IdGetter} interface returning the PIDs
+     * listed in the meta type information.
+     * 
+     * @see #getPidObjectClasses(String)
+     */
+    private static final IdGetter PID_GETTER = new IdGetter()
+    {
+        public String[] getIds( MetaTypeInformation metaTypeInformation )
+        {
+            return metaTypeInformation.getPids();
+        }
+    };
+
+    /** 
+     * The implementation of the {@link IdGetter} interface returning the
+     * factory PIDs listed in the meta type information.
+     * 
+     * @see #getFactoryPidObjectClasses(String)
+     */
+    private static final IdGetter FACTORY_PID_GETTER = new IdGetter()
+    {
+        public String[] getIds( MetaTypeInformation metaTypeInformation )
+        {
+            return metaTypeInformation.getFactoryPids();
+        }
+    };
+
 }