FELIX-1800: Multiple related fixes:
  - list all configurations in the drop down, even such without metatype information
  - prevent NullPointerException rendering configuration binding information if
    no bundle with the bound location is installed
  - properly attach the generic configuration property entry to the parent element
  - ask all bundles for metatype information of a configuration if no bundle
    is installed whose bundle location equals the configuration binding

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@829261 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 1ad0539..123b11c 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
@@ -373,7 +373,7 @@
         {
             // 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 );
 
@@ -403,10 +403,7 @@
                     name = pid;
                 }
 
-                if ( ocd != null )
-                {
-                    optionsPlain.put( pid, name );
-                }
+                optionsPlain.put( pid, name );
             }
 
             printOptionsForm( pw, optionsPlain, "configSelection_pid", "configure", "Configure" );
@@ -758,21 +755,30 @@
         }
         else
         {
+            // if the configuration is bound to a bundle location which
+            // is not related to an installed bundle, we just print the
+            // raw bundle location binding
             Bundle bundle = this.getBundle( config.getBundleLocation() );
-
-            Dictionary headers = bundle.getHeaders( locale );
-            String name = ( String ) headers.get( Constants.BUNDLE_NAME );
-            if ( name == null )
+            if ( bundle == null )
             {
-                location = bundle.getSymbolicName();
+                location = config.getBundleLocation();
             }
             else
             {
-                location = name + " (" + bundle.getSymbolicName() + ")";
-            }
+                Dictionary headers = bundle.getHeaders( locale );
+                String name = ( String ) headers.get( Constants.BUNDLE_NAME );
+                if ( name == null )
+                {
+                    location = bundle.getSymbolicName();
+                }
+                else
+                {
+                    location = name + " (" + bundle.getSymbolicName() + ")";
+                }
 
-            Version v = Version.parseVersion( ( String ) headers.get( Constants.BUNDLE_VERSION ) );
-            location += ", Version " + v.toString();
+                Version v = Version.parseVersion( ( String ) headers.get( Constants.BUNDLE_VERSION ) );
+                location += ", Version " + v.toString();
+            }
         }
         json.key( "bundleLocation" );
         json.value( location );
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 b8e2548..8943a25 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
@@ -91,7 +91,7 @@
      * 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
@@ -127,43 +127,43 @@
 
     protected ObjectClassDefinition getObjectClassDefinition( Configuration config, String locale )
     {
-
-        // if the configuration is not bound, search in the bundles
-        if ( config.getBundleLocation() == null )
-        {
-            // if the configuration is a factory one, use the factory PID
-            if ( config.getFactoryPid() != null )
-            {
-                return this.getObjectClassDefinition( config.getFactoryPid(), locale );
-            }
-
-            // otherwise use the configuration PID
-            return this.getObjectClassDefinition( config.getPid(), locale );
-        }
-
-        MetaTypeService mts = this.getMetaTypeService();
-        if ( mts != null )
+        // if the configuration is bound, try to get the object class
+        // definition from the bundle installed from the given location
+        if ( config.getBundleLocation() != null )
         {
             Bundle bundle = this.getBundle( config.getBundleLocation() );
             if ( bundle != null )
             {
-                MetaTypeInformation mti = mts.getMetaTypeInformation( bundle );
-                if ( mti != null )
+                MetaTypeService mts = this.getMetaTypeService();
+                if ( mts != null )
                 {
-                    // check by factory PID
-                    if ( config.getFactoryPid() != null )
+                    MetaTypeInformation mti = mts.getMetaTypeInformation( bundle );
+                    if ( mti != null )
                     {
-                        return mti.getObjectClassDefinition( config.getFactoryPid(), locale );
-                    }
+                        // check by factory PID
+                        if ( config.getFactoryPid() != null )
+                        {
+                            return mti.getObjectClassDefinition( config.getFactoryPid(), locale );
+                        }
 
-                    // otherwise check by configuration PID
-                    return mti.getObjectClassDefinition( config.getPid(), locale );
+                        // otherwise check by configuration PID
+                        return mti.getObjectClassDefinition( config.getPid(), locale );
+                    }
                 }
             }
         }
 
-        // fallback to nothing found
-        return null;
+        // get here if the configuration is not bound or if no
+        // bundle with the bound location is installed. We search
+        // all bundles for a matching [factory] PID
+        // if the configuration is a factory one, use the factory PID
+        if ( config.getFactoryPid() != null )
+        {
+            return this.getObjectClassDefinition( config.getFactoryPid(), locale );
+        }
+
+        // otherwise use the configuration PID
+        return this.getObjectClassDefinition( config.getPid(), locale );
     }
 
 
@@ -269,7 +269,7 @@
      * 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
      */
@@ -278,10 +278,10 @@
         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()
@@ -292,10 +292,10 @@
         }
     };
 
-    /** 
+    /**
      * 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()
diff --git a/webconsole/src/main/resources/res/ui/configmanager.js b/webconsole/src/main/resources/res/ui/configmanager.js
index 4235651..e45fbc4 100644
--- a/webconsole/src/main/resources/res/ui/configmanager.js
+++ b/webconsole/src/main/resources/res/ui/configmanager.js
@@ -173,18 +173,20 @@
         propsValue += key + ' =  ' + props[key] + '\r\n';
     }
 
-    return tr( "content", null, [
-        td( "content aligntop", null, [
-            text( "Properties" )
-        ]),
-        td( "content", { style: { width: "99%" } }, [
-            createElement( "textarea", null, {
-                    name: "properties",
-                    style: { height: "50%", width: "99%" }
-                }, [ text( propsValue ) ] ),
-            text( "Enter Name-Value pairs of configuration properties" )
+    parent.appendChild(
+        tr( "content", null, [
+            td( "content aligntop", null, [
+                text( "Properties" )
+            ]),
+            td( "content", { style: { width: "99%" } }, [
+                createElement( "textarea", null, {
+                        name: "properties",
+                        style: { height: "50%", width: "99%" }
+                    }, [ text( propsValue ) ] ),
+                text( "Enter Name-Value pairs of configuration properties" )
+            ])
         ])
-    ]);        
+    );        
 }
 
 function printForm( /* Element */ parent, obj ) {