FELIX-3849 : Support setting configuration binding

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1649069 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigAdminSupport.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigAdminSupport.java
index ad6fd7a..d15d94d 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigAdminSupport.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigAdminSupport.java
@@ -307,6 +307,29 @@
                 }
             }
 
+            final String location = request.getParameter(ConfigManager.LOCATION);
+            if ( location == null || location.trim().length() == 0 )
+            {
+                if ( config.getBundleLocation() != null )
+                {
+                    config.setBundleLocation(null);
+                    // workaround for Felix Config Admin 1.2.8 not clearing dynamic
+                    // bundle location when clearing static bundle location. In
+                    // this case we first set the static bundle location to the
+                    // dynamic bundle location and then try to set both to null
+                    if ( config.getBundleLocation() != null )
+                    {
+                        config.setBundleLocation( "??invalid:bundle/location" ); //$NON-NLS-1$
+                        config.setBundleLocation( null );
+                    }
+                }
+            } else
+            {
+                if ( config.getBundleLocation() == null || !config.getBundleLocation().equals(location) )
+                {
+                    config.setBundleLocation(location);
+                }
+            }
             config.update( updateProps );
         }
 
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigManager.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigManager.java
index d00532a..211deee 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigManager.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigManager.java
@@ -59,6 +59,7 @@
     static final String ACTION_APPLY = "apply"; //$NON-NLS-1$
     static final String ACTION_UNBIND = "unbind"; //$NON-NLS-1$
     static final String PROPERTY_LIST = "propertylist"; //$NON-NLS-1$
+    static final String LOCATION = "$location"; //$NON-NLS-1$
 
     static final String CONFIGURATION_ADMIN_NAME = "org.osgi.service.cm.ConfigurationAdmin"; //$NON-NLS-1$
     static final String META_TYPE_NAME = "org.osgi.service.metatype.MetaTypeService"; //$NON-NLS-1$
diff --git a/webconsole/src/main/resources/OSGI-INF/l10n/bundle.properties b/webconsole/src/main/resources/OSGI-INF/l10n/bundle.properties
index ec5495e..c5a1cea 100644
--- a/webconsole/src/main/resources/OSGI-INF/l10n/bundle.properties
+++ b/webconsole/src/main/resources/OSGI-INF/l10n/bundle.properties
@@ -175,7 +175,7 @@
 config.info.binding=Configuration Binding
 config.info.unbound=Unbound or new configuration 
 config.unbind.btn=Unbind
-config.unbind.tip=Unbind Configuration from Bundle
+config.unbind.tip=Unbind configuration from bundle
 config.del.ask=Are you sure to delete this configuration ?
 config.del.config=Configuration: 
 config.del.bundle=Bundle: 
diff --git a/webconsole/src/main/resources/res/ui/config.css b/webconsole/src/main/resources/res/ui/config.css
index 2946b18..eef4258 100644
--- a/webconsole/src/main/resources/res/ui/config.css
+++ b/webconsole/src/main/resources/res/ui/config.css
@@ -37,3 +37,4 @@
 	float: left; margin-right: .3em;
 }
 td.col_Exists_body div.ui-icon { margin-left:auto; margin-right: auto }
+input.placeholder-active { color: #AAA !important }
\ No newline at end of file
diff --git a/webconsole/src/main/resources/res/ui/config.js b/webconsole/src/main/resources/res/ui/config.js
index 4096d5f..9c66195 100644
--- a/webconsole/src/main/resources/res/ui/config.js
+++ b/webconsole/src/main/resources/res/ui/config.js
@@ -95,6 +95,13 @@
         });
     formEl.appendChild( inputEl );
     
+    inputEl = createElement( "input", null, {
+        type: "hidden",
+        name: "$location",
+        id: "lochidden"
+    });
+    formEl.appendChild( inputEl );
+    
     var tableEl = createElement( "table", null, {
             border: 0,
             width: "100%"
@@ -264,10 +271,12 @@
         );
     }
     
-    var binding = obj.bundleLocation;
+    var binding = obj.bundle_location;
     if (!binding)
     {
         binding = i18n.unbound;
+    } else {
+    	$("#lochidden").val(binding);
     }
     
     parent.appendChild( tr( null, null, [
@@ -275,11 +284,47 @@
                 text( i18n.binding )
             ]),
             td( null, null, [
-                text( binding )
+                createElement( "input", null, {
+                    type: "text",
+                    name: "$location",
+                    style: { width: '99%' },
+                    value: binding,
+                    id: "locinput"
+                })                             
             ])
         ])
     );
-
+    if ( binding === i18n.unbound ) {
+    	$("#locinput").addClass("placeholder-active");
+    }
+	$("#locinput").on("focus", function() {
+	    if ($("#locinput").val() === i18n.unbound) {
+	        $("#locinput").removeClass("placeholder-active");
+	        $("#locinput").val("");
+	    }
+	});
+	$("#locinput").on("blur", function() {
+	    if($("#locinput").val() === "") {
+	        $("#locinput").val(i18n.unbound);
+	        $("#locinput").addClass("placeholder-active");
+	    }
+	});
+	$("#locinput").on("keydown", function(event) {
+	    if (event.keyCode == 27){
+	        $("#locinput").val("");
+	    }
+	});
+	if ( obj.bundleLocation && obj.bundleLocation != "" ) {
+	    parent.appendChild( tr( null, null, [
+	                                         td( null, null, [
+	                                             text( "" )
+	                                         ]),
+	                                         td( null, null, [
+	                                             text( obj.bundleLocation )
+	                                         ])
+	                                     ])
+	                                 );		
+	}
 }
 
 
@@ -545,7 +590,7 @@
 	configBody    = configTable.find('tbody');
 	configRow     = configBody.find('tr:eq(0)').clone();
 	factoryRow    = configBody.find('tr:eq(1)').clone();
-
+	
 	// setup button - cannot inline in dialog option because of i18n
 	var _buttons = {};
 	_buttons[i18n.abort] = function() {
@@ -564,6 +609,12 @@
 	    	unbindConfig($(this).attr('__pid'), $(this).attr('__location'));
 	}
 	_buttons[i18n.save] = function() {
+		if ( $("#locinput").val() === i18n.unbound ) {
+			$("#lochidden").val("");			
+		} else {
+			$("#lochidden").val($("#locinput").val());			
+		}
+		
 		// get all the configuration properties names
 		var propListElement = $(this).find('form').find('[name=propertylist]');
 		var propListArray = propListElement.val().split(',');