FELIX-583, FELIX-584, FELIX-588: Separate the lists of the ManagedServiceFactory
and ManagedService with existing configuration objects.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@667498 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/AjaxConfigManagerAction.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/AjaxConfigManagerAction.java
index 9dc7aad..52fcd97 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/AjaxConfigManagerAction.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/AjaxConfigManagerAction.java
@@ -34,9 +34,11 @@
import javax.servlet.http.HttpServletResponse;
import org.apache.felix.webconsole.Action;
+import org.apache.felix.webconsole.internal.Util;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
+import org.json.JSONWriter;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
@@ -71,26 +73,43 @@
public boolean performAction( HttpServletRequest request, HttpServletResponse response ) throws IOException
{
+ // needed multiple times below
+ String pid = request.getParameter( ConfigManager.PID );
+
// should actually apply the configuration before redirecting
- if ( request.getParameter( "apply" ) != null )
+ if ( request.getParameter( "create" ) != null && pid != null )
+ {
+ ConfigurationAdmin ca = this.getConfigurationAdmin();
+ if ( ca != null )
+ {
+ Configuration config = ca.createFactoryConfiguration( pid, null );
+ pid = config.getPid();
+ }
+ }
+ else if ( request.getParameter( "apply" ) != null )
{
return applyConfiguration( request );
}
- JSONObject result = new JSONObject();
-
- String pid = request.getParameter( ConfigManager.PID );
boolean isFactory = pid == null;
if ( isFactory )
{
pid = request.getParameter( "factoryPid" );
}
+ // send the result
+ response.setContentType( "text/javascript" );
+ response.setCharacterEncoding( "UTF-8" );
+
+ JSONWriter result = new JSONWriter( response.getWriter() );
+
if ( pid != null )
{
try
{
+ result.object();
this.configForm( result, pid, isFactory, getLocale( request ) );
+ result.endObject();
}
catch ( Exception e )
{
@@ -98,15 +117,11 @@
}
}
- // send the result
- response.setContentType( "text/javascript" );
- response.getWriter().print( result.toString() );
-
return false;
}
- private void configForm( JSONObject json, String pid, boolean isFactory, Locale loc ) throws IOException,
+ private void configForm( JSONWriter json, String pid, boolean isFactory, Locale loc ) throws IOException,
JSONException
{
String locale = ( loc == null ) ? null : loc.toString();
@@ -133,8 +148,10 @@
return;
}
- json.put( ConfigManager.PID, pid );
- json.put( "isFactory", isFactory );
+ json.key( ConfigManager.PID );
+ json.value( pid );
+ json.key( "isFactory" );
+ json.value( isFactory );
Dictionary props = null;
ObjectClassDefinition ocd;
@@ -152,7 +169,18 @@
if ( props != null )
{
- JSONObject properties = new JSONObject();
+
+ json.key( "title" );
+ json.value( pid );
+ json.key( "description" );
+ json
+ .value( "Please enter configuration properties for this configuration in the field below. This configuration has no associated description" );
+
+ json.key( "propertylist" );
+ json.value( "properties" );
+
+ json.key( "properties" );
+ json.object();
for ( Enumeration pe = props.keys(); pe.hasMoreElements(); )
{
Object key = pe.nextElement();
@@ -164,19 +192,11 @@
&& !key.equals( ConfigurationAdmin.SERVICE_BUNDLELOCATION )
&& !key.equals( ConfigurationAdmin.SERVICE_FACTORYPID ) )
{
- properties.put( String.valueOf( key ), props.get( key ) );
+ json.key( String.valueOf( key ) );
+ json.value( props.get( key ) );
}
-
}
-
- json.put( "title", pid );
- json
- .put(
- "description",
- "Please enter configuration properties for this configuration in the field below. This configuration has no associated description" );
-
- json.put( "propertylist", "properties" );
- json.put( "properties", properties );
+ json.endObject();
}
@@ -187,7 +207,7 @@
}
- private Dictionary mergeWithMetaType( Dictionary props, ObjectClassDefinition ocd, JSONObject json )
+ private Dictionary mergeWithMetaType( Dictionary props, ObjectClassDefinition ocd, JSONWriter json )
throws JSONException
{
@@ -199,11 +219,13 @@
if ( ocd != null )
{
- json.put( "title", ocd.getName() );
+ json.key( "title" );
+ json.value( ocd.getName() );
if ( ocd.getDescription() != null )
{
- json.put( "description", ocd.getDescription() );
+ json.key( "description" );
+ json.value( ocd.getDescription() );
}
AttributeDefinition[] ad = ocd.getAttributeDefinitions( ObjectClassDefinition.ALL );
@@ -214,7 +236,8 @@
for ( int i = 0; i < ad.length; i++ )
{
- JSONObject entry = new JSONObject();
+ json.key( ad[i].getID() );
+ json.object();
Object value = props.get( ad[i].getID() );
if ( value == null )
@@ -233,18 +256,22 @@
}
}
- entry.put( "name", ad[i].getName() );
+ json.key( "name" );
+ json.value( ad[i].getName() );
+ json.key( "type" );
if ( ad[i].getOptionLabels() != null && ad[i].getOptionLabels().length > 0 )
{
- JSONObject type = new JSONObject();
- type.put( "labels", Arrays.asList( ad[i].getOptionLabels() ) );
- type.put( "values", Arrays.asList( ad[i].getOptionValues() ) );
- entry.put( "type", type );
+ json.object();
+ json.key( "labels" );
+ json.value( Arrays.asList( ad[i].getOptionLabels() ) );
+ json.key( "values" );
+ json.value( Arrays.asList( ad[i].getOptionValues() ) );
+ json.endObject();
}
else
{
- entry.put( "type", ad[i].getType() );
+ json.value( ad[i].getType() );
}
if ( ad[i].getCardinality() == 0 )
@@ -258,7 +285,8 @@
{
value = Array.get( value, 0 );
}
- entry.put( "value", value );
+ json.key( "value" );
+ json.value( value );
}
else
{
@@ -276,19 +304,22 @@
tmp.put( value );
value = tmp;
}
- entry.put( "values", value );
+ json.key( "values" );
+ json.value( value );
}
if ( ad[i].getDescription() != null )
{
- entry.put( "description", ad[i].getDescription() );
+ json.key( "description" );
+ json.value( ad[i].getDescription() );
}
- json.put( ad[i].getID(), entry );
+ json.endObject();
propertyList.put( ad[i].getID() );
}
- json.put( "propertylist", propertyList );
+ json.key( "propertylist" );
+ json.value( propertyList );
}
// nothing more to display
@@ -299,12 +330,13 @@
}
- private void addConfigurationInfo( Configuration config, JSONObject json, String locale ) throws JSONException
+ private void addConfigurationInfo( Configuration config, JSONWriter json, String locale ) throws JSONException
{
if ( config.getFactoryPid() != null )
{
- json.put( "factoryPID", config.getFactoryPid() );
+ json.key( "factoryPID" );
+ json.value( config.getFactoryPid() );
}
String location;
@@ -330,7 +362,8 @@
Version v = Version.parseVersion( ( String ) headers.get( Constants.BUNDLE_VERSION ) );
location += ", Version " + v.toString();
}
- json.put( "bundleLocation", location );
+ json.key( "bundleLocation" );
+ json.value( location );
}
@@ -360,7 +393,7 @@
// request.setAttribute(ATTR_REDIRECT_PARAMETERS, "pid=" +
// config.getPid());
- return true;
+ return false;
}
String propertyList = request.getParameter( "propertylist" );
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 0a43e07..839e038 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
@@ -22,7 +22,6 @@
import java.util.Dictionary;
import java.util.Iterator;
import java.util.Locale;
-import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Map.Entry;
@@ -31,13 +30,12 @@
import javax.servlet.http.HttpServletResponse;
import org.apache.felix.webconsole.Render;
-import org.apache.felix.webconsole.internal.Util;
-import org.apache.felix.webconsole.internal.core.SetStartLevelAction;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
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.metatype.ObjectClassDefinition;
@@ -86,6 +84,13 @@
pw.println( "</td>" );
pw.println( "</tr>" );
+ pw.println( "<tr class='content' id='factoryField'>" );
+ pw.println( "<td class='content'>Factory Configurations</th>" );
+ pw.println( "<td class='content'>" );
+ this.listFactoryConfigurations( pw, optionalMetaType, getLocale( request ) );
+ pw.println( "</td>" );
+ pw.println( "</tr>" );
+
pw.println( "</table>" );
}
@@ -104,11 +109,106 @@
try
{
- // get a list of all pids for which MetaData exists
- Map metaDataPids = this.getMetadataPids();
-
// sorted map of options
- SortedMap options = new TreeMap( String.CASE_INSENSITIVE_ORDER );
+ SortedMap optionsPlain = new TreeMap( String.CASE_INSENSITIVE_ORDER );
+
+ // find all ManagedServices to get the PIDs
+ ServiceReference[] refs = this.getBundleContext().getServiceReferences( ManagedService.class.getName(),
+ null );
+ for ( int i = 0; refs != null && i < refs.length; i++ )
+ {
+ Object pidObject = refs[i].getProperty( Constants.SERVICE_PID );
+ if ( pidObject instanceof String )
+ {
+ String pid = ( String ) pidObject;
+ String name;
+ ObjectClassDefinition ocd = this.getObjectClassDefinition( refs[i].getBundle(), pid, locale );
+ if ( ocd != null )
+ {
+ name = ocd.getName() + " (";
+ name += pid + ")";
+ }
+ else
+ {
+ name = pid;
+ }
+
+ if ( ocd != null || optionalMetaType )
+ {
+ optionsPlain.put( pid, name );
+ }
+ }
+ }
+
+ // get a sorted list of configuration PIDs
+ Configuration[] cfgs = ca.listConfigurations( null );
+ for ( int i = 0; cfgs != null && i < cfgs.length; i++ )
+ {
+
+ // ignore configuration object if an entry already exists in the
+ // map
+ String pid = cfgs[i].getPid();
+ if ( optionsPlain.containsKey( pid ) )
+ {
+ continue;
+ }
+
+ // insert and entry for the pid
+ ObjectClassDefinition ocd = this.getObjectClassDefinition( cfgs[i], locale );
+ String name;
+ if ( ocd != null )
+ {
+ name = ocd.getName() + " (";
+ name += pid + ")";
+ }
+ else
+ {
+ name = pid;
+ }
+
+ if ( ocd != null || optionalMetaType )
+ {
+ optionsPlain.put( pid, name );
+ }
+ }
+
+ // pw.println( "<form method='post' name='configSelection' onSubmit='configure(); return false;'" );
+ pw.println( "<select class='select' name='pid' id='configSelection_pid' onChange='configure();'>" );
+ for ( Iterator ei = optionsPlain.entrySet().iterator(); ei.hasNext(); )
+ {
+ Entry entry = ( Entry ) ei.next();
+ pw.print( "<option value='" + entry.getKey() + "'>" );
+ pw.print( entry.getValue() );
+ pw.println( "</option>" );
+ }
+ pw.println( "</select>" );
+ pw.println( " " );
+ pw.println( "<input class='submit' type='button' value='Configure' onClick='configure();' />" );
+ // pw.println( "</form>" );
+ }
+ catch ( Exception e )
+ {
+ // write a message or ignore
+ }
+ }
+
+
+ private void listFactoryConfigurations( PrintWriter pw, boolean optionalMetaType, Locale loc )
+ {
+
+ ConfigurationAdmin ca = this.getConfigurationAdmin();
+ if ( ca == null )
+ {
+ pw.print( "Configuration Admin Service not available" );
+ return;
+ }
+
+ String locale = ( loc != null ) ? loc.toString() : null;
+
+ try
+ {
+ // sorted map of options
+ SortedMap optionsFactory = new TreeMap( String.CASE_INSENSITIVE_ORDER );
// find all ManagedServiceFactories to get the factoryPIDs
ServiceReference[] refs = this.getBundleContext().getServiceReferences(
@@ -133,97 +233,13 @@
if ( ocd != null || optionalMetaType )
{
- options.put( "factoryPid=" + pid, name );
+ optionsFactory.put( pid, name );
}
}
}
- // get a sorted list of configuration PIDs
- Configuration[] cfgs = ca.listConfigurations( null );
- for ( int i = 0; cfgs != null && i < cfgs.length; i++ )
- {
-
- // ignore configuration object if an entry already exists in the
- // map
- String pid = cfgs[i].getPid();
- if ( options.containsKey( "pid=" + pid ) || options.containsKey( "factoryPid=" + pid ) )
- {
- continue;
- }
-
- Dictionary props = cfgs[i].getProperties();
-
- // insert and entry for the pid
- ObjectClassDefinition ocd = this.getObjectClassDefinition( cfgs[i], locale );
- String name;
- if ( ocd != null )
- {
- name = ocd.getName() + " (";
- name += pid + ")";
-
- // remove from the list of known pids
- metaDataPids.remove( pid );
-
- }
- else
- {
- name = pid;
- }
-
- if ( ocd != null || optionalMetaType )
- {
- options.put( "pid=" + pid, name );
- }
-
- // if the configuration is part of a factory, ensure an entry
- // for the factory
- if ( cfgs[i].getFactoryPid() != null )
- {
- pid = cfgs[i].getFactoryPid();
- if ( options.containsValue( "factoryPid=" + pid ) )
- {
- continue;
- }
-
- String existing = ( String ) options.remove( "pid=" + pid );
- if ( existing != null )
- {
- options.put( "factoryPid=" + pid, existing );
- }
- else
- {
- Bundle bundle = this.getBundle( cfgs[i].getBundleLocation() );
- ocd = this.getObjectClassDefinition( bundle, pid, locale );
- if ( ocd != null )
- {
- options.put( "factoryPid=" + pid, ocd.getName() );
- }
- else if ( optionalMetaType )
- {
- options.put( "factoryPid=" + pid, pid );
- }
- }
- }
- }
-
- // If there are any meta data PIDs for which there is no existing
- // configuration, we add them to the list to create configuration
- if ( !metaDataPids.isEmpty() )
- {
- for ( Iterator mdpi = metaDataPids.entrySet().iterator(); mdpi.hasNext(); )
- {
- Entry mdp = ( Entry ) mdpi.next();
- ObjectClassDefinition ocd = this.getObjectClassDefinition( ( Bundle ) mdp.getValue(),
- ( String ) mdp.getKey(), locale );
- options.put( "pid=" + mdp.getKey(), ocd.getName() + " (" + mdp.getKey() + ")" );
- }
- }
-
- pw.println( "<form method='post' name='configSelection' onSubmit='configure(); return false;'" );
- pw.println( "<input type='hidden' name='" + Util.PARAM_ACTION + "' value='" + SetStartLevelAction.NAME
- + "'>" );
- pw.println( "<select class='select' name='pid' onChange='configure();'>" );
- for ( Iterator ei = options.entrySet().iterator(); ei.hasNext(); )
+ pw.println( "<select class='select' name='pid' id='configSelection_factory' onChange='create();'>" );
+ for ( Iterator ei = optionsFactory.entrySet().iterator(); ei.hasNext(); )
{
Entry entry = ( Entry ) ei.next();
pw.print( "<option value='" + entry.getKey() + "'>" );
@@ -232,9 +248,7 @@
}
pw.println( "</select>" );
pw.println( " " );
- pw.println( "<input class='submit' type='submit' value='Configure' />" );
- pw.println( "</form>" );
-
+ pw.println( "<input class='submit' type='button' value='Create' onClick='create();' />" );
}
catch ( Exception e )
{
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 225268b..53e701b 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
@@ -118,17 +118,14 @@
// if the configuration is not bound, search in the bundles
if ( config.getBundleLocation() == null )
{
- ObjectClassDefinition ocd = this.getObjectClassDefinition( config.getPid(), locale );
- if ( ocd != null )
- {
- return ocd;
- }
-
- // if none, check whether there might be one for the 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 );
}
MetaTypeService mts = this.getMetaTypeService();
@@ -140,19 +137,14 @@
MetaTypeInformation mti = mts.getMetaTypeInformation( bundle );
if ( mti != null )
{
- // try OCD by PID first
- ObjectClassDefinition ocd = mti.getObjectClassDefinition( config.getPid(), locale );
- if ( ocd != null )
- {
- return ocd;
- }
-
- // if none, check whether there might be one for the factory
- // PID
+ // 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 );
}
}
}
diff --git a/webconsole/src/main/resources/res/ui/configmanager.js b/webconsole/src/main/resources/res/ui/configmanager.js
index e0e0027..a538a84 100644
--- a/webconsole/src/main/resources/res/ui/configmanager.js
+++ b/webconsole/src/main/resources/res/ui/configmanager.js
@@ -21,20 +21,43 @@
if (!span) {
return;
}
- var select = document.configSelection.pid;
+ var select = document.getElementById('configSelection_pid');
var pid = select.options[select.selectedIndex].value;
- var parm = '?action=ajaxConfigManager&' + pid;
+ var parm = '?action=ajaxConfigManager&pid=' + pid;
sendRequest('GET', parm, displayConfigForm);
}
-function displayConfigForm(obj) {
+
+function create() {
var span = document.getElementById('configField');
if (!span) {
return;
}
- var innerHtml = '<tr class="content" id="configField">' + span.innerHTML + '</tr>';
+ var select = document.getElementById('configSelection_factory');
+ var pid = select.options[select.selectedIndex].value;
+ var parm = '?action=ajaxConfigManager&create=true&pid=' + pid;
+ sendRequest('GET', parm, displayConfigForm);
+}
+
+function displayConfigForm(obj) {
+ var span1 = document.getElementById('configField');
+ var span2 = document.getElementById('factoryField');
+ if (!span1 && !span2) {
+ return;
+ }
+
+ var innerHtml = "";
+
+ if (span1) {
+ innerHtml += '<tr class="content" id="configField">' + span1.innerHTML + '</tr>';
+ }
+ if (span2) {
+ innerHtml += '<tr class="content" id="factoryField">' + span2.innerHTML + '</tr>';
+ }
+
innerHtml += '<tr class="content">';
innerHtml += '<th colspan="2" class="content" >' + obj.title + '</th></tr>';
+
innerHtml += '<tr class="content">';
innerHtml += '<td class="content"> </td>';
innerHtml += '<td class="content">';
@@ -68,8 +91,10 @@
innerHtml += '</table>';
innerHtml += '</form>';
innerHtml += '</td></tr>';
+
innerHtml += printConfigurationInfo(obj);
- span.parentNode.innerHTML = innerHtml;
+
+ span1.parentNode.innerHTML = innerHtml;
}
function printTextArea(props) {
@@ -101,6 +126,11 @@
// assume attr.values and multiselect
innerHtml += createMultiSelect(prop, attr.values, attr.type, '99%');
innerHtml += '<br />';
+ } else if (attr.values.length == 0) {
+ var spanElement = createSpan(prop, "", attr.type);
+ innerHtml += '<span id="' + spanElement.id + '">';
+ innerHtml += spanElement.innerHTML;
+ innerHtml += '</span>';
} else {
for (var vidx in attr.values) {
var spanElement = createSpan(prop, attr.values[vidx], attr.type);
@@ -129,14 +159,22 @@
innerHtml += '<tr class="content">';
innerHtml += '<td class="content">Persistent Identity (PID)</td>';
innerHtml += '<td class="content">' + obj.pid + '</td></tr>';
+
if (obj.factoryPID) {
innerHtml += '<tr class="content">';
innerHtml += '<td class="content">Factory Peristent Identifier (Factory PID)</td>';
innerHtml += '<td class="content">' + obj.factoryPID + '</td></tr>';
}
+
+ var binding = obj.bundleLocation;
+ if (!binding) {
+ binding = "Unbound or new configuration";
+ }
+
innerHtml += '<tr class="content">';
innerHtml += '<td class="content">Configuration Binding</td>';
- innerHtml += '<td class="content">' + obj.bundleLocation + '</td></tr>';
+ innerHtml += '<td class="content">' + binding + '</td></tr>';
+
return innerHtml;
}