felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fmesc...@apache.org
Subject svn commit: r668622 - in /felix/trunk/webconsole/src/main: java/org/apache/felix/webconsole/internal/compendium/ java/org/apache/felix/webconsole/internal/servlet/ resources/res/ui/
Date Tue, 17 Jun 2008 11:43:01 GMT
Author: fmeschbe
Date: Tue Jun 17 04:43:01 2008
New Revision: 668622

URL: http://svn.apache.org/viewvc?rev=668622&view=rev
Log:
FELIX-566 Support restful URLs for Configuration support

Removed:
    felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/AjaxConfigManagerAction.java
Modified:
    felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ConfigManager.java
    felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ConfigManagerBase.java
    felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
    felix/trunk/webconsole/src/main/resources/res/ui/configmanager.js

Modified: felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ConfigManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ConfigManager.java?rev=668622&r1=668621&r2=668622&view=diff
==============================================================================
--- felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ConfigManager.java
(original)
+++ felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ConfigManager.java
Tue Jun 17 04:43:01 2008
@@ -17,31 +17,49 @@
 package org.apache.felix.webconsole.internal.compendium;
 
 
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.reflect.Array;
+import java.util.Arrays;
+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.StringTokenizer;
 import java.util.TreeMap;
+import java.util.Vector;
 import java.util.Map.Entry;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.felix.webconsole.Render;
+import org.apache.felix.webconsole.internal.Util;
+import org.apache.felix.webconsole.internal.servlet.OsgiManager;
+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.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.metatype.AttributeDefinition;
 import org.osgi.service.metatype.ObjectClassDefinition;
 
 
 /**
  * The <code>ConfigManager</code> TODO
  */
-public class ConfigManager extends ConfigManagerBase implements Render
+public class ConfigManager extends ConfigManagerBase
 {
 
     public static final String NAME = "configMgr";
@@ -50,95 +68,181 @@
 
     public static final String PID = "pid";
 
+    public static final String factoryPID = "factoryPid";
 
-    public String getLabel()
+    private static final String PLACEHOLDER_PID = "[Temporary PID replaced by real PID upon
save]";
+
+
+    public String getTitle()
     {
         return LABEL;
     }
 
 
-    public String getName()
+    public String getLabel()
     {
         return NAME;
     }
 
 
-    public void render( HttpServletRequest request, HttpServletResponse response ) throws
IOException
+    protected void doPost( HttpServletRequest request, HttpServletResponse response ) throws
IOException
     {
+        // needed multiple times below
+        String pid = request.getParameter( ConfigManager.PID );
+        if ( pid == null )
+        {
+            String info = request.getPathInfo();
+            pid = info.substring( info.lastIndexOf( '/' ) + 1 );
+        }
 
-        // true if MetaType service information is not required
-        boolean optionalMetaType = false;
+        ConfigurationAdmin ca = this.getConfigurationAdmin();
 
-        PrintWriter pw = response.getWriter();
+        // ignore this request if the pid and/or configuration admin is missing
+        if ( pid == null || ca == null )
+        {
+            // should log this here !!
+            return;
+        }
 
-        pw.println( "<script type='text/javascript' src='res/ui/configmanager.js'></script>"
);
+        // the configuration to operate on (to be created or "missing")
+        Configuration config = null;
 
-        pw.println( "<table class='content' cellpadding='0' cellspacing='0' width='100%'>"
);
+        // should actually apply the configuration before redirecting
+        if ( request.getParameter( "create" ) != null )
+        {
+            if ( ca != null )
+            {
+                config = new PlaceholderConfiguration( pid ); // ca.createFactoryConfiguration(
pid, null );
+                pid = config.getPid();
+            }
+        }
+        else if ( request.getParameter( "apply" ) != null )
+        {
+            String redirect = applyConfiguration( request, ca, pid );
+            if ( redirect != null )
+            {
+                response.sendRedirect( redirect );
+            }
 
-        pw.println( "<tr class='content' id='configField'>" );
-        pw.println( "<td class='content'>Configurations</th>" );
-        pw.println( "<td class='content'>" );
-        this.listConfigurations( pw, optionalMetaType, getLocale( request ) );
-        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>" );
+            return;
+        }
+
+        if ( config == null )
+        {
+            config = getConfiguration( ca, pid );
+        }
+
+        // send the result
+        response.setContentType( "text/javascript" );
+        response.setCharacterEncoding( "UTF-8" );
+        printConfigurationJson( response.getWriter(), pid, config, getLocale( request ) );
     }
 
 
-    private void listConfigurations( PrintWriter pw, boolean optionalMetaType, Locale loc
)
+    public void renderContent( HttpServletRequest request, HttpServletResponse response )
throws IOException
     {
 
+        // true if MetaType service information is not required
+        boolean optionalMetaType = false;
+
+        Locale loc = getLocale( request );
+        String locale = ( loc != null ) ? loc.toString() : null;
+
+        PrintWriter pw = response.getWriter();
+
+        String appRoot = (String) request.getAttribute( OsgiManager.ATTR_APP_ROOT );
+        pw.println( "<script src='" + appRoot + "/res/ui/configmanager.js' language='JavaScript'></script>"
);
+
+        pw.println( "<table class='content' cellpadding='0' cellspacing='0' width='100%'>"
);
+
         ConfigurationAdmin ca = this.getConfigurationAdmin();
         if ( ca == null )
         {
+            pw.println( "<tr class='content' id='configField'>" );
+            pw.println( "<td class='content'>&nbsp;</th>" );
+            pw.println( "<td class='content'>" );
             pw.print( "Configuration Admin Service not available" );
-            return;
+            pw.println( "</td>" );
+            pw.println( "</tr>" );
+        }
+        else
+        {
+            pw.println( "<tr class='content' id='configField'>" );
+            pw.println( "<td class='content'>Configurations</th>" );
+            pw.println( "<td class='content'>" );
+            this.listConfigurations( pw, ca, optionalMetaType, locale );
+            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, ca, optionalMetaType, locale );
+            pw.println( "</td>" );
+            pw.println( "</tr>" );
         }
 
-        String locale = ( loc != null ) ? loc.toString() : null;
+        pw.println( "</table>" );
 
-        try
+        // if a configuration is addressed, display it immediately
+        Configuration config = getConfiguration( getConfigurationAdmin(), request.getPathInfo()
);
+        if ( config != null )
         {
-            // sorted map of options
-            SortedMap optionsPlain = new TreeMap( String.CASE_INSENSITIVE_ORDER );
+            Util.startScript( pw );
 
-            // 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;
-                    }
+            pw.println( "var configuration=" );
+            printConfigurationJson( pw, config.getPid(), config, getLocale( request ) );
+            pw.println( ";" );
 
-                    if ( ocd != null || optionalMetaType )
-                    {
-                        optionsPlain.put( pid, name );
-                    }
+            pw.println( "displayConfigForm(configuration);" );
+
+            Util.endScript( pw );
+        }
+    }
+
+
+    private Configuration getConfiguration( ConfigurationAdmin ca, String pid )
+    {
+        if ( ca != null )
+        {
+            // only use last part of the pathInfo
+            pid = pid.substring( pid.lastIndexOf( '/' ) + 1 );
+
+            try
+            {
+                // we use listConfigurations to not create configuration
+                // objects persistently without the user providing actual
+                // configuration
+                String filter = "(" + Constants.SERVICE_PID + "=" + pid + ")";
+                Configuration[] configs = ca.listConfigurations( filter );
+                if ( configs != null && configs.length > 0 )
+                {
+                    return configs[0];
                 }
             }
+            catch ( InvalidSyntaxException ise )
+            {
+                // should print message
+            }
+            catch ( IOException ioe )
+            {
+                // should print message
+            }
+        }
 
-            // get a sorted list of configuration PIDs
+        // fallback to no configuration at all
+        return null;
+    }
+
+
+    private void listConfigurations( PrintWriter pw, ConfigurationAdmin ca, boolean optionalMetaType,
String locale )
+    {
+        try
+        {
+            // start with ManagedService instances
+            SortedMap optionsPlain = getServices( ManagedService.class.getName(), optionalMetaType,
locale );
+
+            // add in existing configuration (not duplicating ManagedServices)
             Configuration[] cfgs = ca.listConfigurations( null );
             for ( int i = 0; cfgs != null && i < cfgs.length; i++ )
             {
@@ -170,19 +274,22 @@
                 }
             }
 
-            //            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( "&nbsp;&nbsp;" );
-            pw.println( "<input class='submit' type='button' value='Configure' onClick='configure();'
/>" );
-            //            pw.println( "</form>" );
+            printOptionsForm( pw, optionsPlain, "configSelection_pid", "configure", "Configure"
);
+        }
+        catch ( Exception e )
+        {
+            // write a message or ignore
+        }
+    }
+
+
+    private void listFactoryConfigurations( PrintWriter pw, ConfigurationAdmin ca, boolean
optionalMetaType,
+        String locale )
+    {
+        try
+        {
+            SortedMap optionsFactory = getServices( ManagedServiceFactory.class.getName(),
optionalMetaType, locale );
+            printOptionsForm( pw, optionsFactory, "configSelection_factory", "create", "Create"
);
         }
         catch ( Exception e )
         {
@@ -191,66 +298,565 @@
     }
 
 
-    private void listFactoryConfigurations( PrintWriter pw, boolean optionalMetaType, Locale
loc )
+    private SortedMap getServices( String serviceClass, boolean optionalMetaType, String
locale )
+        throws InvalidSyntaxException
     {
+        // sorted map of options
+        SortedMap optionsFactory = new TreeMap( String.CASE_INSENSITIVE_ORDER );
 
-        ConfigurationAdmin ca = this.getConfigurationAdmin();
-        if ( ca == null )
+        // find all ManagedServiceFactories to get the factoryPIDs
+        ServiceReference[] refs = this.getBundleContext().getServiceReferences( serviceClass,
null );
+        for ( int i = 0; refs != null && i < refs.length; i++ )
         {
-            pw.print( "Configuration Admin Service not available" );
-            return;
+            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 )
+                {
+                    optionsFactory.put( pid, name );
+                }
+            }
         }
 
-        String locale = ( loc != null ) ? loc.toString() : null;
+        return optionsFactory;
+    }
 
-        try
+
+    private void printOptionsForm( PrintWriter pw, SortedMap options, String formId, String
submitMethod,
+        String submitLabel )
+    {
+        pw.println( "<select class='select' name='pid' id='" + formId + "' onChange='"
+ submitMethod + "();'>" );
+        for ( Iterator ei = options.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( "&nbsp;&nbsp;" );
+        pw.println( "<input class='submit' type='button' value='" + submitLabel + "' onClick='"
+ submitMethod
+            + "();' />" );
+
+    }
+
+
+    private void printConfigurationJson( PrintWriter pw, String pid, Configuration config,
Locale locale )
+        throws IOException
+    {
+
+        JSONWriter result = new JSONWriter( pw );
+
+        if ( pid != null )
+        {
+            try
+            {
+                result.object();
+                this.configForm( result, pid, config, locale );
+                result.endObject();
+            }
+            catch ( Exception e )
+            {
+                // add message
+            }
+        }
+
+    }
+
+
+    private void configForm( JSONWriter json, String pid, Configuration config, Locale loc
) throws IOException,
+        JSONException
+    {
+        String locale = ( loc == null ) ? null : loc.toString();
+
+        json.key( ConfigManager.PID );
+        json.value( pid );
+
+        if ( pid == PLACEHOLDER_PID )
+        {
+            json.key( ConfigManager.factoryPID );
+            json.value( config.getFactoryPid() );
+        }
+
+        Dictionary props = null;
+        ObjectClassDefinition ocd;
+        if ( config != null )
+        {
+            props = config.getProperties();
+            ocd = this.getObjectClassDefinition( config, locale );
+        }
+        else
+        {
+            ocd = this.getObjectClassDefinition( pid, locale );
+        }
+
+        props = this.mergeWithMetaType( props, ocd, json );
+
+        if ( props != null )
+        {
+
+            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();
+
+                // ignore well known special properties
+                if ( !key.equals( Constants.SERVICE_PID ) && !key.equals( Constants.SERVICE_DESCRIPTION
)
+                    && !key.equals( Constants.SERVICE_ID ) && !key.equals(
Constants.SERVICE_RANKING )
+                    && !key.equals( Constants.SERVICE_VENDOR )
+                    && !key.equals( ConfigurationAdmin.SERVICE_BUNDLELOCATION )
+                    && !key.equals( ConfigurationAdmin.SERVICE_FACTORYPID ) )
+                {
+                    json.key( String.valueOf( key ) );
+                    json.value( props.get( key ) );
+                }
+            }
+            json.endObject();
+
+        }
+
+        if ( config != null )
+        {
+            this.addConfigurationInfo( config, json, locale );
+        }
+    }
+
+
+    private Dictionary mergeWithMetaType( Dictionary props, ObjectClassDefinition ocd, JSONWriter
json )
+        throws JSONException
+    {
+
+        if ( props == null )
         {
-            // sorted map of options
-            SortedMap optionsFactory = new TreeMap( String.CASE_INSENSITIVE_ORDER );
+            props = new Hashtable();
+        }
+
+        if ( ocd != null )
+        {
+
+            json.key( "title" );
+            json.value( ocd.getName() );
+
+            if ( ocd.getDescription() != null )
+            {
+                json.key( "description" );
+                json.value( ocd.getDescription() );
+            }
+
+            AttributeDefinition[] ad = ocd.getAttributeDefinitions( ObjectClassDefinition.ALL
);
+            if ( ad != null )
+            {
+
+                JSONArray propertyList = new JSONArray();
+
+                for ( int i = 0; i < ad.length; i++ )
+                {
+                    json.key( ad[i].getID() );
+                    json.object();
+
+                    Object value = props.get( ad[i].getID() );
+                    if ( value == null )
+                    {
+                        value = ad[i].getDefaultValue();
+                        if ( value == null )
+                        {
+                            if ( ad[i].getCardinality() == 0 )
+                            {
+                                value = "";
+                            }
+                            else
+                            {
+                                value = new String[0];
+                            }
+                        }
+                    }
+
+                    json.key( "name" );
+                    json.value( ad[i].getName() );
+
+                    json.key( "type" );
+                    if ( ad[i].getOptionLabels() != null && ad[i].getOptionLabels().length
> 0 )
+                    {
+                        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
+                    {
+                        json.value( ad[i].getType() );
+                    }
 
-            // find all ManagedServiceFactories to get the factoryPIDs
-            ServiceReference[] refs = this.getBundleContext().getServiceReferences(
-                ManagedServiceFactory.class.getName(), null );
-            for ( int i = 0; refs != null && i < refs.length; i++ )
-            {
-                Object factoryPid = refs[i].getProperty( Constants.SERVICE_PID );
-                if ( factoryPid instanceof String )
-                {
-                    String pid = ( String ) factoryPid;
-                    String name;
-                    ObjectClassDefinition ocd = this.getObjectClassDefinition( refs[i].getBundle(),
pid, locale );
-                    if ( ocd != null )
+                    if ( ad[i].getCardinality() == 0 )
                     {
-                        name = ocd.getName() + " (";
-                        name += pid + ")";
+                        // scalar
+                        if ( value instanceof Vector )
+                        {
+                            value = ( ( Vector ) value ).get( 0 );
+                        }
+                        else if ( value.getClass().isArray() )
+                        {
+                            value = Array.get( value, 0 );
+                        }
+                        json.key( "value" );
+                        json.value( value );
                     }
                     else
                     {
-                        name = pid;
+                        if ( value instanceof Vector )
+                        {
+                            value = new JSONArray( ( Vector ) value );
+                        }
+                        else if ( value.getClass().isArray() )
+                        {
+                            value = new JSONArray( Arrays.asList( ( Object[] ) value ) );
+                        }
+                        else
+                        {
+                            JSONArray tmp = new JSONArray();
+                            tmp.put( value );
+                            value = tmp;
+                        }
+                        json.key( "values" );
+                        json.value( value );
                     }
 
-                    if ( ocd != null || optionalMetaType )
+                    if ( ad[i].getDescription() != null )
                     {
-                        optionsFactory.put( pid, name );
+                        json.key( "description" );
+                        json.value( ad[i].getDescription() );
                     }
+
+                    json.endObject();
+                    propertyList.put( ad[i].getID() );
                 }
+
+                json.key( "propertylist" );
+                json.value( propertyList );
+            }
+
+            // nothing more to display
+            props = null;
+        }
+
+        return props;
+    }
+
+
+    private void addConfigurationInfo( Configuration config, JSONWriter json, String locale
) throws JSONException
+    {
+
+        if ( config.getFactoryPid() != null )
+        {
+            json.key( "factoryPID" );
+            json.value( config.getFactoryPid() );
+        }
+
+        String location;
+        if ( config.getBundleLocation() == null )
+        {
+            location = "None";
+        }
+        else
+        {
+            Bundle bundle = this.getBundle( config.getBundleLocation() );
+
+            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();
+        }
+        json.key( "bundleLocation" );
+        json.value( location );
+    }
+
 
-            pw.println( "<select class='select' name='pid' id='configSelection_factory'
onChange='create();'>" );
-            for ( Iterator ei = optionsFactory.entrySet().iterator(); ei.hasNext(); )
+    private String applyConfiguration( HttpServletRequest request, ConfigurationAdmin ca,
String pid )
+        throws IOException
+    {
+        if ( request.getParameter( "delete" ) != null )
+        {
+            // only delete if the PID is not our place holder
+            if ( !PLACEHOLDER_PID.equals( pid ) )
             {
-                Entry entry = ( Entry ) ei.next();
-                pw.print( "<option value='" + entry.getKey() + "'>" );
-                pw.print( entry.getValue() );
-                pw.println( "</option>" );
+                // TODO: should log this here !!
+                Configuration config = ca.getConfiguration( pid, null );
+                config.delete();
             }
-            pw.println( "</select>" );
-            pw.println( "&nbsp;&nbsp;" );
-            pw.println( "<input class='submit' type='button' value='Create' onClick='create();'
/>" );
+            return ""; // up a level
         }
-        catch ( Exception e )
+
+        String factoryPid = request.getParameter( ConfigManager.factoryPID );
+        Configuration config = null;
+        
+        String propertyList = request.getParameter( "propertylist" );
+        if ( propertyList == null )
         {
-            // write a message or ignore
+            String propertiesString = request.getParameter( "properties" );
+
+            if ( propertiesString != null )
+            {
+                byte[] propBytes = propertiesString.getBytes( "ISO-8859-1" );
+                ByteArrayInputStream bin = new ByteArrayInputStream( propBytes );
+                Properties props = new Properties();
+                props.load( bin );
+
+                config = getConfiguration( ca, pid, factoryPid );
+                config.update( props );
+            }
+        }
+        else
+        {
+            config = getConfiguration( ca, pid, factoryPid );
+
+            Dictionary props = config.getProperties();
+            if ( props == null )
+            {
+                props = new Hashtable();
+            }
+
+            Map adMap = this.getAttributeDefinitionMap( config, null );
+            if ( adMap != null )
+            {
+                StringTokenizer propTokens = new StringTokenizer( propertyList, "," );
+                while ( propTokens.hasMoreTokens() )
+                {
+                    String propName = propTokens.nextToken();
+                    AttributeDefinition ad = ( AttributeDefinition ) adMap.get( propName
);
+                    if ( ad == null || ( ad.getCardinality() == 0 && ad.getType()
== AttributeDefinition.STRING ) )
+                    {
+                        String prop = request.getParameter( propName );
+                        if ( prop != null )
+                        {
+                            props.put( propName, prop );
+                        }
+                    }
+                    else if ( ad.getCardinality() == 0 )
+                    {
+                        // scalar of non-string
+                        String prop = request.getParameter( propName );
+                        props.put( propName, this.toType( ad.getType(), prop ) );
+                    }
+                    else
+                    {
+                        // array or vector of any type
+                        Vector vec = new Vector();
+
+                        String[] properties = request.getParameterValues( propName );
+                        if ( properties != null )
+                        {
+                            for ( int i = 0; i < properties.length; i++ )
+                            {
+                                vec.add( this.toType( ad.getType(), properties[i] ) );
+                            }
+                        }
+
+                        // but ensure size
+                        int maxSize = Math.abs( ad.getCardinality() );
+                        if ( vec.size() > maxSize )
+                        {
+                            vec.setSize( maxSize );
+                        }
+
+                        if ( ad.getCardinality() < 0 )
+                        {
+                            // keep the vector
+                            props.put( propName, vec );
+                        }
+                        else
+                        {
+                            // convert to an array
+                            props.put( propName, this.toArray( ad.getType(), vec ) );
+                        }
+                    }
+                }
+            }
+
+            config.update( props );
+        }
+
+        // redirect to the new configuration (if existing)
+        return (config != null) ? config.getPid() : "";
+    }
+
+
+    private Configuration getConfiguration( ConfigurationAdmin ca, String pid, String factoryPid
) throws IOException
+    {
+        if ( factoryPid != null )
+        {
+            return ca.createFactoryConfiguration( factoryPid, null );
+        }
+
+        return ca.getConfiguration( pid, null );
+    }
+
+
+    private Object toType( int type, String value )
+    {
+        switch ( type )
+        {
+            case AttributeDefinition.BOOLEAN:
+                return Boolean.valueOf( value );
+            case AttributeDefinition.BYTE:
+                return Byte.valueOf( value );
+            case AttributeDefinition.CHARACTER:
+                char c = ( value.length() > 0 ) ? value.charAt( 0 ) : 0;
+                return new Character( c );
+            case AttributeDefinition.DOUBLE:
+                return Double.valueOf( value );
+            case AttributeDefinition.FLOAT:
+                return Float.valueOf( value );
+            case AttributeDefinition.LONG:
+                return Long.valueOf( value );
+            case AttributeDefinition.INTEGER:
+                return Integer.valueOf( value );
+            case AttributeDefinition.SHORT:
+                return Short.valueOf( value );
+
+            default:
+                // includes AttributeDefinition.STRING
+                return value;
+        }
+    }
+
+
+    private Object toArray( int type, Vector values )
+    {
+        int size = values.size();
+
+        // short cut for string array
+        if ( type == AttributeDefinition.STRING )
+        {
+            return values.toArray( new String[size] );
+        }
+
+        Object array;
+        switch ( type )
+        {
+            case AttributeDefinition.BOOLEAN:
+                array = new boolean[size];
+            case AttributeDefinition.BYTE:
+                array = new byte[size];
+            case AttributeDefinition.CHARACTER:
+                array = new char[size];
+            case AttributeDefinition.DOUBLE:
+                array = new double[size];
+            case AttributeDefinition.FLOAT:
+                array = new float[size];
+            case AttributeDefinition.LONG:
+                array = new long[size];
+            case AttributeDefinition.INTEGER:
+                array = new int[size];
+            case AttributeDefinition.SHORT:
+                array = new short[size];
+            default:
+                // unexpected, but assume string
+                array = new String[size];
+        }
+
+        for ( int i = 0; i < size; i++ )
+        {
+            Array.set( array, i, values.get( i ) );
+        }
+
+        return array;
+    }
+
+    private static class PlaceholderConfiguration implements Configuration
+    {
+
+        private final String factoryPid;
+        private String bundleLocation;
+
+
+        PlaceholderConfiguration( String factoryPid )
+        {
+            this.factoryPid = factoryPid;
+        }
+
+
+        public String getPid()
+        {
+            return PLACEHOLDER_PID;
+        }
+
+
+        public String getFactoryPid()
+        {
+            return factoryPid;
+        }
+
+
+        public void setBundleLocation( String bundleLocation )
+        {
+            this.bundleLocation = bundleLocation;
+        }
+
+
+        public String getBundleLocation()
+        {
+            return bundleLocation;
+        }
+
+
+        public Dictionary getProperties()
+        {
+            // dummy configuration has no properties
+            return null;
         }
+
+
+        public void update()
+        {
+            // dummy configuration cannot be updated
+        }
+
+
+        public void update( Dictionary properties )
+        {
+            // dummy configuration cannot be updated
+        }
+
+
+        public void delete()
+        {
+            // dummy configuration cannot be deleted
+        }
+
     }
+
 }

Modified: felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ConfigManagerBase.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ConfigManagerBase.java?rev=668622&r1=668621&r2=668622&view=diff
==============================================================================
--- felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ConfigManagerBase.java
(original)
+++ felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ConfigManagerBase.java
Tue Jun 17 04:43:01 2008
@@ -23,68 +23,37 @@
 
 import javax.servlet.http.HttpServletRequest;
 
-import org.apache.felix.webconsole.internal.BaseManagementPlugin;
+import org.apache.felix.webconsole.internal.BaseWebConsolePlugin;
 import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
 import org.osgi.service.cm.Configuration;
 import org.osgi.service.cm.ConfigurationAdmin;
 import org.osgi.service.metatype.AttributeDefinition;
 import org.osgi.service.metatype.MetaTypeInformation;
 import org.osgi.service.metatype.MetaTypeService;
 import org.osgi.service.metatype.ObjectClassDefinition;
-import org.osgi.util.tracker.ServiceTracker;
 
 
 /**
  * The <code>ConfigManagerBase</code> TODO
  * 
  */
-abstract class ConfigManagerBase extends BaseManagementPlugin
+abstract class ConfigManagerBase extends BaseWebConsolePlugin
 {
     private static final String CONFIGURATION_ADMIN_NAME = ConfigurationAdmin.class.getName();
-    
-    private static final String META_TYPE_NAME = MetaTypeService.class.getName();
-
-    private ServiceTracker configurationAdmin;
-
-    private ServiceTracker metaTypeService;
-
-
-    public void activate( BundleContext bundleContext )
-    {
-        super.activate( bundleContext );
-
-        configurationAdmin = new ServiceTracker( bundleContext, ConfigurationAdmin.class.getName(),
null );
-        configurationAdmin.open();
-        metaTypeService = new ServiceTracker( bundleContext, MetaTypeService.class.getName(),
null );
-        metaTypeService.open();
-    }
-
 
-    public void destroy()
-    {
-        if ( configurationAdmin != null )
-        {
-            configurationAdmin.close();
-        }
-        if ( metaTypeService != null )
-        {
-            metaTypeService.close();
-        }
-    }
+    private static final String META_TYPE_NAME = MetaTypeService.class.getName();
 
 
     protected ConfigurationAdmin getConfigurationAdmin()
     {
-        //TODO: getService(CONFIGURATION_ADMIN_NAME)
-        return ( ConfigurationAdmin ) configurationAdmin.getService();
+        return ( ConfigurationAdmin ) getService( CONFIGURATION_ADMIN_NAME );
     }
 
 
     protected MetaTypeService getMetaTypeService()
     {
-        //TODO: getService(META_TYPE_NAME)
-        return ( MetaTypeService ) metaTypeService.getService();
+        //TODO: 
+        return ( MetaTypeService ) getService( META_TYPE_NAME );
     }
 
 
@@ -142,7 +111,7 @@
                     {
                         return mti.getObjectClassDefinition( config.getFactoryPid(), locale
);
                     }
-                    
+
                     // otherwise check by configuration PID
                     return mti.getObjectClassDefinition( config.getPid(), locale );
                 }

Modified: felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java?rev=668622&r1=668621&r2=668622&view=diff
==============================================================================
--- felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
(original)
+++ felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
Tue Jun 17 04:43:01 2008
@@ -40,7 +40,6 @@
 import org.apache.felix.webconsole.internal.Logger;
 import org.apache.felix.webconsole.internal.OsgiManagerPlugin;
 import org.apache.felix.webconsole.internal.Util;
-import org.apache.felix.webconsole.internal.compendium.AjaxConfigManagerAction;
 import org.apache.felix.webconsole.internal.compendium.ComponentConfigurationPrinter;
 import org.apache.felix.webconsole.internal.compendium.ComponentRenderAction;
 import org.apache.felix.webconsole.internal.compendium.ConfigManager;
@@ -77,6 +76,8 @@
 
     public static final String ATTR_LABEL_MAP = OsgiManager.class.getName() + ".labelMap";
 
+    public static final String ATTR_APP_ROOT = OsgiManager.class.getName() + ".appRoot";
+
     /**
      * The name and value of a parameter which will prevent redirection to a
      * render after the action has been executed (value is "_noredir_"). This
@@ -124,10 +125,10 @@
     private static final String DEFAULT_MANAGER_ROOT = "/system/console";
 
     private static final Class[] PLUGIN_CLASSES =
-        { AjaxConfigManagerAction.class, ComponentConfigurationPrinter.class, ComponentRenderAction.class,
-            ConfigManager.class, BundlesServlet.class, InstallAction.class, SetStartLevelAction.class,
-            ConfigurationRender.class, GCAction.class, ShutdownAction.class, ShutdownRender.class,
VMStatRender.class,
-            BundleRepositoryRender.class, LicenseServlet.class };
+        { ComponentConfigurationPrinter.class, ComponentRenderAction.class, ConfigManager.class,
BundlesServlet.class,
+            InstallAction.class, SetStartLevelAction.class, ConfigurationRender.class, GCAction.class,
+            ShutdownAction.class, ShutdownRender.class, VMStatRender.class, BundleRepositoryRender.class,
+            LicenseServlet.class };
 
     private BundleContext bundleContext;
 
@@ -317,6 +318,8 @@
         if ( plugin != null )
         {
             req.setAttribute( ATTR_LABEL_MAP, labelMap );
+            req.setAttribute( ATTR_APP_ROOT, request.getContextPath() + request.getServletPath()
);
+            
             plugin.service( req, res );
         }
         else

Modified: felix/trunk/webconsole/src/main/resources/res/ui/configmanager.js
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/resources/res/ui/configmanager.js?rev=668622&r1=668621&r2=668622&view=diff
==============================================================================
--- felix/trunk/webconsole/src/main/resources/res/ui/configmanager.js (original)
+++ felix/trunk/webconsole/src/main/resources/res/ui/configmanager.js Tue Jun 17 04:43:01
2008
@@ -23,8 +23,8 @@
     }
     var select = document.getElementById('configSelection_pid');
     var pid = select.options[select.selectedIndex].value;
-    var parm = '?action=ajaxConfigManager&pid=' + pid;
-    sendRequest('GET', parm, displayConfigForm);
+    var parm = pluginRoot + '/' + pid;
+    sendRequest('POST', parm, displayConfigForm);
 }
 
 
@@ -35,8 +35,8 @@
     }
     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);
+    var parm = pluginRoot + '/' + pid + '?create=true';
+    sendRequest('POST', parm, displayConfigForm);
 }
 
 function displayConfigForm(obj) {
@@ -61,9 +61,15 @@
     innerHtml += '<tr class="content">';
     innerHtml += '<td class="content">&nbsp;</td>';
     innerHtml += '<td class="content">';
-    innerHtml += '<form method="post">';
+    innerHtml += '<form method="post" action="' + pluginRoot + '/' + obj.pid + '">';
     innerHtml += '<input type="hidden" name="apply" value="true" />';
-    innerHtml += '<input type="hidden" name="pid" value="' + obj.pid + '" />';
+    
+    // add the factory PID as a hidden form field if present
+    if (obj.factoryPid)
+    {
+        innerHtml += '<input type="hidden" name="factoryPid" value="' + obj.factoryPid
+ '" />';
+    }
+    
     innerHtml += '<input type="hidden" name="action" value="ajaxConfigManager" />';
     innerHtml += '<table border="0" width="100%">';
     if (obj.description) {



Mime
View raw message