Author: fmeschbe
Date: Thu Jun 19 04:08:47 2008
New Revision: 669450

URL: http://svn.apache.org/viewvc?rev=669450&view=rev
Log:
FELIX-566 Enable RESTful URLs for component list and unify display of bundles 
and components

Added:
    
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentsServlet.java
      - copied, changed from r668621, 
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentRenderAction.java
    felix/trunk/webconsole/src/main/resources/res/ui/datatable.js
Removed:
    
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentRenderAction.java
Modified:
    
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentConfigurationPrinter.java
    
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/BundlesServlet.java
    
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
    felix/trunk/webconsole/src/main/resources/res/ui/bundles.js

Modified: 
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentConfigurationPrinter.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentConfigurationPrinter.java?rev=669450&r1=669449&r2=669450&view=diff
==============================================================================
--- 
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentConfigurationPrinter.java
 (original)
+++ 
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentConfigurationPrinter.java
 Thu Jun 19 04:08:47 2008
@@ -107,7 +107,7 @@
 
         pw.println( "  Bundle" + component.getBundle().getSymbolicName() + " 
(" + component.getBundle().getBundleId()
             + ")" );
-        pw.println( "  State=" + ComponentRenderAction.toStateString( 
component.getState() ) );
+        pw.println( "  State=" + ComponentsServlet.toStateString( 
component.getState() ) );
         pw.println( "  DefaultState=" + ( component.isDefaultEnabled() ? 
"enabled" : "disabled" ) );
         pw.println( "  Activation=" + ( component.isImmediate() ? "immediate" 
: "delayed" ) );
 

Copied: 
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentsServlet.java
 (from r668621, 
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentRenderAction.java)
URL: 
http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentsServlet.java?p2=felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentsServlet.java&p1=felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentRenderAction.java&r1=668621&r2=669450&rev=669450&view=diff
==============================================================================
--- 
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentRenderAction.java
 (original)
+++ 
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentsServlet.java
 Thu Jun 19 04:08:47 2008
@@ -32,18 +32,17 @@
 import org.apache.felix.scr.Component;
 import org.apache.felix.scr.Reference;
 import org.apache.felix.scr.ScrService;
-import org.apache.felix.webconsole.Action;
-import org.apache.felix.webconsole.Render;
+import org.apache.felix.webconsole.internal.BaseWebConsolePlugin;
 import org.apache.felix.webconsole.internal.Util;
-import org.json.JSONArray;
+import org.apache.felix.webconsole.internal.servlet.OsgiManager;
 import org.json.JSONException;
-import org.json.JSONObject;
+import org.json.JSONWriter;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.component.ComponentConstants;
 
 
-public class ComponentRenderAction extends AbstractScrPlugin implements 
Render, Action
+public class ComponentsServlet extends BaseWebConsolePlugin
 {
 
     public static final String NAME = "components";
@@ -52,30 +51,29 @@
 
     public static final String COMPONENT_ID = "componentId";
 
-    public static final String OPERATION = "op";
-
-    public static final String OPERATION_DETAILS = "details";
+    public static final String OPERATION = "action";
 
     public static final String OPERATION_ENABLE = "enable";
 
     public static final String OPERATION_DISABLE = "disable";
 
+    private static final String SCR_SERVICE = ScrService.class.getName();
+
 
-    public String getName()
+    public String getTitle()
     {
-        return NAME;
+        return LABEL;
     }
 
 
     public String getLabel()
     {
-        return LABEL;
+        return NAME;
     }
 
 
-    public boolean performAction( HttpServletRequest request, 
HttpServletResponse response ) throws IOException
+    protected void doPost( HttpServletRequest request, HttpServletResponse 
response ) throws IOException
     {
-
         ScrService scrService = getScrService();
         if ( scrService != null )
         {
@@ -86,11 +84,7 @@
             if ( component != null )
             {
                 String op = request.getParameter( OPERATION );
-                if ( OPERATION_DETAILS.equals( op ) )
-                {
-                    return sendAjaxDetails( component, response );
-                }
-                else if ( OPERATION_ENABLE.equals( op ) )
+                if ( OPERATION_ENABLE.equals( op ) )
                 {
                     component.enable();
                 }
@@ -98,215 +92,196 @@
                 {
                     component.disable();
                 }
+
+                sendAjaxDetails( component, response );
             }
 
         }
-
-        return true;
     }
 
 
-    public void render( HttpServletRequest request, HttpServletResponse 
response ) throws IOException
+    protected void renderContent( HttpServletRequest request, 
HttpServletResponse response ) throws IOException
     {
-
         PrintWriter pw = response.getWriter();
 
-        this.header( pw );
+        String appRoot = ( String ) request.getAttribute( 
OsgiManager.ATTR_APP_ROOT );
+        pw.println( "<script src='" + appRoot + "/res/ui/datatable.js' 
language='JavaScript'></script>" );
 
-        pw.println( "<tr class='content'>" );
-        pw.println( "<td colspan='5' class='content'>&nbsp;</th>" );
-        pw.println( "</tr>" );
+        Util.startScript( pw );
 
-        this.tableHeader( pw );
+        pw.print( "var components = " );
+        renderResult( request, pw );
+        pw.println( ";" );
 
-        ScrService scrService = getScrService();
-        if ( scrService == null )
-        {
-            pw.println( "<tr class='content'>" );
-            pw
-                .println( "<td class='content' colspan='5'>Apache Felix 
Declarative Service required for this function</td>" );
-            pw.println( "</tr>" );
-        }
-        else
+        pw.println( "renderDataTable( components );" );
+
+        Util.endScript( pw );
+    }
+
+
+    private void renderResult( HttpServletRequest request, PrintWriter pw ) 
throws IOException
+    {
+        JSONWriter jw = new JSONWriter( pw );
+        try
         {
-            Component[] components = scrService.getComponents();
-            if ( components == null || components.length == 0 )
-            {
-                pw.println( "<tr class='content'>" );
-                pw.println( "<td class='content' colspan='5'>No " + 
this.getLabel() + " installed currently</td>" );
-                pw.println( "</tr>" );
+            jw.object();
+
+            jw.key( "numActions" );
+            jw.value( 2 );
 
+            ScrService scrService = getScrService();
+            if ( scrService == null )
+            {
+                jw.key( "error" );
+                jw.value( "Apache Felix Declarative Service required for this 
function" );
             }
             else
             {
+                Component[] components = null;
+                boolean details = false;
 
-                // order components by id
-                TreeMap componentMap = new TreeMap();
-                for ( int i = 0; i < components.length; i++ )
-                {
-                    Component component = components[i];
-                    componentMap.put( component.getName(), component );
-                }
-
-                // render components
-                long previousComponent = -1;
-                for ( Iterator ci = componentMap.values().iterator(); 
ci.hasNext(); )
+                long componentId = getComponentId( request );
+                if ( componentId >= 0 )
                 {
-                    Component component = ( Component ) ci.next();
-                    if ( previousComponent >= 0 )
+                    Component component = scrService.getComponent( componentId 
);
+                    if ( component != null )
                     {
-                        // prepare for injected table information row
-                        pw.println( "<tr id='component" + previousComponent + 
"'></tr>" );
+                        components = new Component[]
+                            { component };
+                        details = true;
                     }
+                }
 
-                    component( pw, component );
-
-                    previousComponent = component.getId();
+                if ( components == null )
+                {
+                    components = scrService.getComponents();
                 }
 
-                if ( previousComponent >= 0 )
+                if ( components == null || components.length == 0 )
                 {
-                    // prepare for injected table information row
-                    pw.println( "<tr id='component" + previousComponent + 
"'></tr>" );
+                    jw.key( "error" );
+                    jw.value( "No components installed currently" );
                 }
-            }
-        }
+                else
+                {
+                    // order components by name
+                    TreeMap componentMap = new TreeMap();
+                    for ( int i = 0; i < components.length; i++ )
+                    {
+                        Component component = components[i];
+                        componentMap.put( component.getName(), component );
+                    }
 
-        pw.println( "<tr class='content'>" );
-        pw.println( "<td colspan='5' class='content'>&nbsp;</th>" );
-        pw.println( "</tr>" );
+                    // render components
+                    jw.key( "data" );
+                    jw.array();
+                    for ( Iterator ci = componentMap.values().iterator(); 
ci.hasNext(); )
+                    {
+                        component( jw, ( Component ) ci.next(), details );
+                    }
+                    jw.endArray();
+                }
+            }
 
-        this.footer( pw );
+            jw.endObject();
+        }
+        catch ( JSONException je )
+        {
+            throw new IOException( je.toString() );
+        }
     }
 
 
-    private void header( PrintWriter pw )
+    private void sendAjaxDetails( Component component, HttpServletResponse 
response ) throws IOException
     {
-        Util.startScript( pw );
-        pw.println( "function showDetails(componentId) {" );
-        pw.println( "    var span = document.getElementById('component' + 
componentId);" );
-        pw.println( "    if (!span) {" );
-        pw.println( "        return;" );
-        pw.println( "    }" );
-        pw.println( "    if (span.innerHTML) {" );
-        pw.println( "        span.innerHTML = '';" );
-        pw.println( "        return;" );
-        pw.println( "    }" );
-        pw.println( "    var parm = '?" + Util.PARAM_ACTION + "=" + NAME + "&" 
+ OPERATION + "=" + OPERATION_DETAILS
-            + "&" + COMPONENT_ID + "=' + componentId;" );
-        pw.println( "    sendRequest('GET', parm, displayComponentDetails);" );
-        pw.println( "}" );
-        pw.println( "function displayComponentDetails(obj) {" );
-        pw.println( "    var span = document.getElementById('component' + 
obj." + COMPONENT_ID + ");" );
-        pw.println( "    if (!span) {" );
-        pw.println( "        return;" );
-        pw.println( "    }" );
-        pw
-            .println( "    var innerHtml = '<td 
class=\"content\">&nbsp;</td><td class=\"content\" colspan=\"4\"><table 
broder=\"0\">';" );
-        pw.println( "    var props = obj.props;" );
-        pw.println( "    for (var i=0; i < props.length; i++) {" );
-        pw
-            .println( "        innerHtml += '<tr><td valign=\"top\" noWrap>' + 
props[i].key + '</td><td valign=\"top\">' + props[i].value + '</td></tr>';" );
-        pw.println( "    }" );
-        pw.println( "    innerHtml += '</table></td>';" );
-        pw.println( "    span.innerHTML = innerHtml;" );
-        pw.println( "}" );
-        Util.endScript( pw );
-
-        pw.println( "<table class='content' cellpadding='0' cellspacing='0' 
width='100%'>" );
-    }
 
+        // send the result
+        response.setContentType( "text/javascript" );
 
-    private void tableHeader( PrintWriter pw )
-    {
-
-        pw.println( "<tr class='content'>" );
-        pw.println( "<th class='content'>ID</th>" );
-        pw.println( "<th class='content' width='100%'>Name</th>" );
-        pw.println( "<th class='content'>Status</th>" );
-        pw.println( "<th class='content' colspan='2'>Actions</th>" );
-        pw.println( "</tr>" );
+        JSONWriter jw = new JSONWriter( response.getWriter() );
+        try
+        {
+            if ( component != null )
+            {
+                component( jw, component, true );
+            }
+        }
+        catch ( JSONException je )
+        {
+            throw new IOException( je.toString() );
+        }
     }
 
 
-    private void footer( PrintWriter pw )
+    private void component( JSONWriter jw, Component component, boolean 
details ) throws JSONException
     {
-        pw.println( "</table>" );
-    }
+        String id = String.valueOf( component.getId() );
+        String name = component.getName();
+        int state = component.getState();
 
+        jw.object();
 
-    private void component( PrintWriter pw, Component component )
-    {
-        String name = component.getName();
+        // component information
+        jw.key( "id" );
+        jw.value( id );
+        jw.key( "name" );
+        jw.value( name );
+        jw.key( "state" );
+        jw.value( toStateString( state ) );
 
-        pw.println( "<tr>" );
-        pw.println( "<td class='content right'>" + component.getId() + "</td>" 
);
-        pw.println( "<td class='content'><a href='javascript:showDetails(" + 
component.getId() + ")'>" + name
-            + "</a></td>" );
-        pw.println( "<td class='content center'>" + toStateString( 
component.getState() ) + "</td>" );
+        // component actions
+        jw.key( "actions" );
+        jw.array();
 
-        boolean enabled = component.getState() == Component.STATE_DISABLED;
-        this.actionForm( pw, enabled, component.getId(), OPERATION_ENABLE, 
"Enable" );
+        jw.object();
+        jw.key( "name" );
+        jw.value( "Enable" );
+        jw.key( "link" );
+        jw.value( OPERATION_ENABLE );
+        jw.key( "enabled" );
+        jw.value( state == Component.STATE_DISABLED );
+        jw.endObject();
 
-        enabled = component.getState() != Component.STATE_DISABLED && 
component.getState() != Component.STATE_DESTROYED;
-        this.actionForm( pw, enabled, component.getId(), OPERATION_DISABLE, 
"Disable" );
+        jw.object();
+        jw.key( "name" );
+        jw.value( "Disable" );
+        jw.key( "link" );
+        jw.value( OPERATION_DISABLE );
+        jw.key( "enabled" );
+        jw.value( state != Component.STATE_DISABLED && state != 
Component.STATE_DESTROYED );
+        jw.endObject();
 
-        pw.println( "</tr>" );
-    }
+        jw.endArray();
 
+        // component details
+        if ( details )
+        {
+            gatherComponentDetails( jw, component );
+        }
 
-    private void actionForm( PrintWriter pw, boolean enabled, long 
componentId, String op, String opLabel )
-    {
-        pw.println( "<form name='form" + componentId + "' method='post'>" );
-        pw.println( "<td class='content' align='right'>" );
-        pw.println( "<input type='hidden' name='" + Util.PARAM_ACTION + "' 
value='" + NAME + "' />" );
-        pw.println( "<input type='hidden' name='" + OPERATION + "' value='" + 
op + "' />" );
-        pw.println( "<input type='hidden' name='" + COMPONENT_ID + "' value='" 
+ componentId + "' />" );
-        pw.println( "<input class='submit' type='submit' value='" + opLabel + 
"'" + ( enabled ? "" : "disabled" )
-            + " />" );
-        pw.println( "</td>" );
-        pw.println( "</form>" );
+        jw.endObject();
     }
 
 
-    private boolean sendAjaxDetails( Component component, HttpServletResponse 
response ) throws IOException
+    private void gatherComponentDetails( JSONWriter jw, Component component ) 
throws JSONException
     {
-        JSONObject result = null;
-        try
-        {
-            if ( component != null )
-            {
+        jw.key( "props" );
+        jw.array();
 
-                JSONArray props = new JSONArray();
-                keyVal( props, "Bundle", 
component.getBundle().getSymbolicName() + " ("
-                    + component.getBundle().getBundleId() + ")" );
-                keyVal( props, "Default State", component.isDefaultEnabled() ? 
"enabled" : "disabled" );
-                keyVal( props, "Activation", component.isImmediate() ? 
"immediate" : "delayed" );
-
-                listServices( props, component );
-                listReferences( props, component );
-                listProperties( props, component );
-
-                result = new JSONObject();
-                result.put( ComponentRenderAction.COMPONENT_ID, 
component.getId() );
-                result.put( "props", props );
-            }
-        }
-        catch ( Exception exception )
-        {
-            // create an empty result on problems
-            result = new JSONObject();
-        }
+        keyVal( jw, "Bundle", component.getBundle().getSymbolicName() + " (" + 
component.getBundle().getBundleId()
+            + ")" );
+        keyVal( jw, "Default State", component.isDefaultEnabled() ? "enabled" 
: "disabled" );
+        keyVal( jw, "Activation", component.isImmediate() ? "immediate" : 
"delayed" );
 
-        // send the result
-        response.setContentType( "text/javascript" );
-        response.getWriter().print( result.toString() );
+        listServices( jw, component );
+        listReferences( jw, component );
+        listProperties( jw, component );
 
-        return false;
+        jw.endArray();
     }
 
 
-    private void listServices( JSONArray props, Component component )
+    private void listServices( JSONWriter jw, Component component )
     {
         String[] services = component.getServices();
         if ( services == null )
@@ -314,7 +289,7 @@
             return;
         }
 
-        keyVal( props, "Service Type", component.isServiceFactory() ? "service 
factory" : "service" );
+        keyVal( jw, "Service Type", component.isServiceFactory() ? "service 
factory" : "service" );
 
         StringBuffer buf = new StringBuffer();
         for ( int i = 0; i < services.length; i++ )
@@ -326,11 +301,11 @@
             buf.append( services[i] );
         }
 
-        keyVal( props, "Services", buf.toString() );
+        keyVal( jw, "Services", buf.toString() );
     }
 
 
-    private void listReferences( JSONArray props, Component component )
+    private void listReferences( JSONWriter jw, Component component )
     {
         Reference[] refs = component.getReferences();
         if ( refs != null )
@@ -354,6 +329,11 @@
                 {
                     for ( int j = 0; j < boundRefs.length; j++ )
                     {
+                        if ( j > 0 )
+                        {
+                            buf.append( "<br />" );
+                        }
+
                         buf.append( "Bound Service ID " );
                         buf.append( boundRefs[j].getProperty( 
Constants.SERVICE_ID ) );
 
@@ -380,13 +360,13 @@
                 }
                 buf.append( "<br />" );
 
-                keyVal( props, "Reference " + refs[i].getName(), 
buf.toString() );
+                keyVal( jw, "Reference " + refs[i].getName(), buf.toString() );
             }
         }
     }
 
 
-    private void listProperties( JSONArray jsonProps, Component component )
+    private void listProperties( JSONWriter jw, Component component )
     {
         Dictionary props = component.getProperties();
         if ( props != null )
@@ -409,22 +389,25 @@
                     buf.append( "<br />" );
                 }
             }
-            keyVal( jsonProps, "Properties", buf.toString() );
+
+            keyVal( jw, "Properties", buf.toString() );
         }
 
     }
 
 
-    private void keyVal( JSONArray props, String key, Object value )
+    private void keyVal( JSONWriter jw, String key, Object value )
     {
         if ( key != null && value != null )
         {
             try
             {
-                JSONObject obj = new JSONObject();
-                obj.put( "key", key );
-                obj.put( "value", value );
-                props.put( obj );
+                jw.object();
+                jw.key( "key" );
+                jw.value( key );
+                jw.key( "value" );
+                jw.value( value );
+                jw.endObject();
             }
             catch ( JSONException je )
             {
@@ -464,21 +447,29 @@
 
     protected long getComponentId( HttpServletRequest request )
     {
-        String componentIdPar = request.getParameter( 
ComponentRenderAction.COMPONENT_ID );
-        if ( componentIdPar != null )
+        String componentIdPar = request.getParameter( 
ComponentsServlet.COMPONENT_ID );
+        if ( componentIdPar == null )
         {
-            try
-            {
-                return Long.parseLong( componentIdPar );
-            }
-            catch ( NumberFormatException nfe )
-            {
-                // TODO: log
-            }
+            String info = request.getPathInfo();
+            componentIdPar = info.substring( info.lastIndexOf( '/' ) + 1 );
+        }
+
+        try
+        {
+            return Long.parseLong( componentIdPar );
+        }
+        catch ( NumberFormatException nfe )
+        {
+            // TODO: log
         }
 
         // no bundleId or wrong format
         return -1;
     }
 
+
+    private ScrService getScrService()
+    {
+        return ( ScrService ) getService( SCR_SERVICE );
+    }
 }

Modified: 
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/BundlesServlet.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/BundlesServlet.java?rev=669450&r1=669449&r2=669450&view=diff
==============================================================================
--- 
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/BundlesServlet.java
 (original)
+++ 
felix/trunk/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/BundlesServlet.java
 Thu Jun 19 04:08:47 2008
@@ -179,7 +179,11 @@
 
         if ( bundle != null )
         {
-            if ( "start".equals( action ) )
+            if ( action == null )
+            {
+                success = true;
+            }
+            else if ( "start".equals( action ) )
             {
                 // start bundle
                 success = true;
@@ -305,7 +309,8 @@
 
         PrintWriter pw = response.getWriter();
 
-        String appRoot = (String) request.getAttribute( 
OsgiManager.ATTR_APP_ROOT );
+        String appRoot = ( String ) request.getAttribute( 
OsgiManager.ATTR_APP_ROOT );
+        pw.println( "<script src='" + appRoot + "/res/ui/datatable.js' 
language='JavaScript'></script>" );
         pw.println( "<script src='" + appRoot + "/res/ui/bundles.js' 
language='JavaScript'></script>" );
 
         Util.startScript( pw );
@@ -314,9 +319,13 @@
         try
         {
             jw.object();
-            jw.key( "startlevel" );
+
+            jw.key( "startLevel" );
             jw.value( getStartLevel().getInitialBundleStartLevel() );
 
+            jw.key( "numActions" );
+            jw.value( 4 );
+
             Bundle bundle = getBundle( request.getPathInfo() );
             Bundle[] bundles = ( bundle != null ) ? new Bundle[]
                 { bundle } : this.getBundles();
@@ -326,7 +335,7 @@
             {
                 Util.sort( bundles );
 
-                jw.key( "bundles" );
+                jw.key( "data" );
 
                 jw.array();
 
@@ -338,6 +347,11 @@
                 jw.endArray();
 
             }
+            else
+            {
+                jw.key( "error" );
+                jw.value( "No Bundles installed currently" );
+            }
 
             jw.endObject();
 
@@ -348,7 +362,7 @@
         }
 
         pw.println( ";" );
-        pw.println( "render(bundleListData.startlevel, 
bundleListData.bundles);" );
+        pw.println( "renderBundle( bundleListData );" );
         Util.endScript( pw );
     }
 
@@ -356,20 +370,31 @@
     private void bundleInfo( JSONWriter jw, Bundle bundle, boolean details ) 
throws JSONException
     {
         jw.object();
-        jw.key( "bundleId" );
+        jw.key( "id" );
         jw.value( bundle.getBundleId() );
         jw.key( "name" );
         jw.value( Util.getName( bundle ) );
         jw.key( "state" );
         jw.value( toStateString( bundle.getState() ) );
-        jw.key( "hasStart" );
-        jw.value( hasStart( bundle ) );
-        jw.key( "hasStop" );
-        jw.value( hasStop( bundle ) );
-        jw.key( "hasUpdate" );
-        jw.value( hasUpdate( bundle ) );
-        jw.key( "hasUninstall" );
-        jw.value( hasUninstall( bundle ) );
+
+        jw.key( "actions" );
+        jw.array();
+
+        if ( bundle.getBundleId() == 0 )
+        {
+            jw.value( false );
+            jw.value( false );
+            jw.value( false );
+            jw.value( false );
+        }
+        else
+        {
+            action( jw, hasStart( bundle ), "start", "Start" );
+            action( jw, hasStop( bundle ), "stop", "Stop" );
+            action( jw, hasUpdate( bundle ), "update", "Update" );
+            action( jw, hasUninstall( bundle ), "uninstall", "Uninstall" );
+        }
+        jw.endArray();
 
         if ( details )
         {
@@ -408,6 +433,19 @@
     }
 
 
+    private void action( JSONWriter jw, boolean enabled, String op, String 
opLabel ) throws JSONException
+    {
+        jw.object();
+        jw.key( "enabled" );
+        jw.value( enabled );
+        jw.key( "name" );
+        jw.value( opLabel );
+        jw.key( "link" );
+        jw.value( op );
+        jw.endObject();
+    }
+
+
     private boolean hasStart( Bundle bundle )
     {
         return bundle.getState() == Bundle.INSTALLED || bundle.getState() == 
Bundle.RESOLVED;

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=669450&r1=669449&r2=669450&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
 Thu Jun 19 04:08:47 2008
@@ -41,7 +41,7 @@
 import org.apache.felix.webconsole.internal.OsgiManagerPlugin;
 import org.apache.felix.webconsole.internal.Util;
 import 
org.apache.felix.webconsole.internal.compendium.ComponentConfigurationPrinter;
-import org.apache.felix.webconsole.internal.compendium.ComponentRenderAction;
+import org.apache.felix.webconsole.internal.compendium.ComponentsServlet;
 import org.apache.felix.webconsole.internal.compendium.ConfigManager;
 import org.apache.felix.webconsole.internal.core.BundlesServlet;
 import org.apache.felix.webconsole.internal.core.InstallAction;
@@ -125,7 +125,7 @@
     private static final String DEFAULT_MANAGER_ROOT = "/system/console";
 
     private static final Class[] PLUGIN_CLASSES =
-        { ComponentConfigurationPrinter.class, ComponentRenderAction.class, 
ConfigManager.class, BundlesServlet.class,
+        { ComponentConfigurationPrinter.class, ComponentsServlet.class, 
ConfigManager.class, BundlesServlet.class,
             InstallAction.class, SetStartLevelAction.class, 
ConfigurationRender.class, GCAction.class,
             ShutdownAction.class, ShutdownRender.class, VMStatRender.class, 
BundleRepositoryRender.class,
             LicenseServlet.class };

Modified: felix/trunk/webconsole/src/main/resources/res/ui/bundles.js
URL: 
http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/resources/res/ui/bundles.js?rev=669450&r1=669449&r2=669450&view=diff
==============================================================================
--- felix/trunk/webconsole/src/main/resources/res/ui/bundles.js (original)
+++ felix/trunk/webconsole/src/main/resources/res/ui/bundles.js Thu Jun 19 
04:08:47 2008
@@ -15,111 +15,29 @@
  * limitations under the License.
  */
 
-function render(/* int */ startlevel, /* Array of Bundle Object */ bundles)
+function renderBundle( /* Array of Data Objects */ bundleData )
 {
 
-    header();
-
-    installForm( startlevel );
+    // number of actions plus 3 -- id, name and state
+    var columns = bundleData.numActions + 3;
+    var startLevel = bundleData.startLevel;
     
-    document.write( "<tr class='content'>" );
-    document.write( "<td colspan='7' class='content'>&nbsp;</th>" );
-    document.write( "</tr>" );
-
-    tableHeader();
-
-    if ( !bundles )
-    {
-        document.write( "<tr class='content'>" );
-        document.write( "<td class='content' colspan='6'>No Bundles installed 
currently</td>" );
-        document.write( "</tr>" );
-    }
-    else
-    {
-        for ( var i = 0; i < bundles.length; i++ )
-        {
-            bundle( bundles[i] );
-        }
-    }
-
-    document.write( "<tr class='content'>" );
-    document.write( "<td colspan='7' class='content'>&nbsp;</th>" );
-    document.write( "</tr>" );
-
-    installForm( startlevel );
-
-    footer();
-}
-
-
-function header()
-{
-    document.write( "<table class='content' cellpadding='0' cellspacing='0' 
width='100%'>" );
-}
-
-
-function tableHeader()
-{
-    document.write( "<tr class='content'>" );
-    document.write( "<th class='content'>ID</th>" );
-    document.write( "<th class='content' width='100%'>Name</th>" );
-    document.write( "<th class='content'>Status</th>" );
-    document.write( "<th class='content' colspan='4'>Actions</th>" );
-    document.write( "</tr>" );
-}
-
-
-function footer()
-{
-    document.write( "</table>" );
-}
-
-
-function bundle( /* Bundle */ bundle )
-{  
-    document.write( "<tr id='bundle" + bundle.bundleId + "'>" );
-    document.write( bundleInternal( bundle ) );
-    document.write( "</tr>" );
-    document.write( "<tr id='bundle" + bundle.bundleId + "_details'>" );
-    if (bundle.props)
-    {
-        document.write( bundleDetails( bundle.props ) );
-    }
-    document.write( "</tr>" );
-}
-
-   
-/* String */ function bundleInternal( /* Bundle */ bundle )
-{
-    var icon = (bundle.props) ? "down" : "right";
-    var theBundle = "<td class='content right'>" + bundle.bundleId + "</td>";
-    theBundle += "<td class='content'><img src='" + appRoot + "/res/imgs/" + 
icon + ".gif' onClick='showDetails(" + bundle.bundleId + ")' id='bundle" + 
bundle.bundleId + "_inline' />";
-    theBundle += " <a href='" + appRoot + "/bundles/" + bundle.bundleId + "'>" 
+ bundle.name + "</a></td>";
-    theBundle += "<td class='content center'>" + bundle.state + "</td>";
+    header( columns );
 
-    // no buttons for system bundle
-    if ( bundle.bundleId == 0 )
+    installForm( startLevel );
+    
+    if (bundleData.error)
     {
-        theBundle += "<td class='content' colspan='4'>&nbsp;</td>";
+        error( columns, bundleData.error );
     }
     else
     {
-        theBundle += actionForm( bundle.hasStart, bundle.bundleId, "start", 
"Start" );
-        theBundle += actionForm( bundle.hasStop, bundle.bundleId, "stop", 
"Stop" );
-        theBundle += actionForm( bundle.hasUpdate, bundle.bundleId, "update", 
"Update" );
-        theBundle += actionForm( bundle.hasUninstall, bundle.bundleId, 
"uninstall", "Uninstall" );
+        data ( bundleData.data );
     }
 
-    return theBundle;
-}
-
+    installForm( startLevel );
 
-/* String */ function actionForm( /* boolean */ enabled, /* long */ bundleId, 
/* String */ action, /* String */ actionLabel )
-{
-    var theButton = "<td class='content' align='right'>";
-    theButton += "<input class='submit' type='button' value='" + actionLabel + 
"'" + ( enabled ? "" : "disabled" ) + " onClick='changeBundle(" + bundleId + ", 
\"" + action + "\");' />";
-    theButton += "</td>";
-    return theButton;
+    footer( columns );
 }
 
 
@@ -142,108 +60,3 @@
     document.write( "</tr>" );
     document.write( "</form>" );
 }
-
-
-function changeBundle(/* long */ bundleId, /* String */ action)
-{
-    var parm = "bundles/" + bundleId + "?action=" + action;
-    sendRequest('POST', parm, bundleChanged);
-}
-
-    
-function bundleChanged(obj)
-{
-    if (obj.reload)
-    {
-        document.location = document.location;
-    }
-    else
-    {
-        var bundleId = obj.bundleId;
-        if (obj.state)
-        {
-            // has status, so draw the line
-            var span = document.getElementById('bundle' + bundleId);
-            if (span)
-            {
-                span.innerHTML = bundleInternal( obj );
-            }
-            
-            if (obj.props)
-            {
-                var span = document.getElementById('bundle' + bundleId + 
'_details');
-                if (span && span.innerHTML)
-                {
-                    span.innerHTML = bundleDetails( obj.props );
-                }
-            }
-            
-        }
-        else
-        {
-            // no status, bundle has been uninstalled
-            var span = document.getElementById('bundle' + bundleId);
-            if (span)
-            {
-                span.parentNode.removeChild(span);
-            }
-            var span = document.getElementById('bundle' + bundleId + 
'_details');
-            if (span)
-            {
-                span.parentNode.removeChild(span);
-            }
-        }
-    }    
-}
-
-    
-function showDetails(bundleId) {
-    var span = document.getElementById('bundle' + bundleId + '_details');
-    if (span)
-    {
-        if (span.innerHTML)
-        {
-            span.innerHTML = '';
-            newLinkValue(bundleId, appRoot + "/res/imgs/right.gif");
-        }
-        else
-        {
-            sendRequest('GET', appRoot + "/bundles/" + bundleId + ".json", 
displayBundleDetails);
-            newLinkValue(bundleId, appRoot + "/res/imgs/down.gif");
-        }
-    }
-}
-
-
-function displayBundleDetails(obj) {
-    var span = document.getElementById('bundle' + obj.bundleId + '_details');
-    if (span)
-    {
-        span.innerHTML = bundleDetails( obj.props );
-    }
-}
-
-
-function newLinkValue(bundleId, newLinkValue)
-{
-    
-    var link = document.getElementById("bundle" + bundleId + "_inline");
-    if (link)
-    {
-        link.src = newLinkValue;
-    }
-}
-
-
-/* String */ function bundleDetails( props )
-{
-        var innerHtml = '<td class=\"content\">&nbsp;</td><td 
class=\"content\" colspan=\"6\"><table broder=\"0\">';
-        for (var i=0; i < props.length; i++)
-        {
-            innerHtml += '<tr><td valign=\"top\" noWrap>' + props[i].key + 
'</td><td valign=\"top\">' + props[i].value + '</td></tr>';
-        }
-        innerHtml += '</table></td>';
-        
-        return innerHtml;
-}
-

Added: felix/trunk/webconsole/src/main/resources/res/ui/datatable.js
URL: 
http://svn.apache.org/viewvc/felix/trunk/webconsole/src/main/resources/res/ui/datatable.js?rev=669450&view=auto
==============================================================================
--- felix/trunk/webconsole/src/main/resources/res/ui/datatable.js (added)
+++ felix/trunk/webconsole/src/main/resources/res/ui/datatable.js Thu Jun 19 
04:08:47 2008
@@ -0,0 +1,258 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+function renderDataTable( /* Array of Data Objects */ components )
+{
+    // number of actions plus 3 -- id, name and state
+    var columns = components.numActions + 3;
+    
+    header( columns );
+
+    if (components.error)
+    {
+        error( columns, components.error );
+    }
+    else
+    {
+        data ( components.data );
+    }
+
+    footer( columns );
+}
+
+
+function header( /* int */ columns )
+{
+    document.write( "<table class='content' cellpadding='0' cellspacing='0' 
width='100%'>" );
+
+    document.write( "<tr class='content'>" );
+    document.write( "<td colspan='" + columns + "' 
class='content'>&nbsp;</th>" );
+    document.write( "</tr>" );
+
+    document.write( "<tr class='content'>" );
+    document.write( "<th class='content'>ID</th>" );
+    document.write( "<th class='content' width='100%'>Name</th>" );
+    document.write( "<th class='content'>Status</th>" );
+    document.write( "<th class='content' colspan='" + (columns - 3) + 
"'>Actions</th>" );
+    document.write( "</tr>" );
+
+}
+
+
+function error( /* int */ columns, /* String */ message )
+{
+    document.write( "<tr class='content'>" );
+    document.write( "<td class='content'>&nbsp;</td>" );
+    document.write( "<td class='content' colspan='" + (columns - 1) + "'>" + 
message + "</td>" );
+    document.write( "</tr>" );
+}
+
+
+function data( /* Array of Object */ dataArray )
+{
+    // render components
+    for ( var idx in dataArray )
+    {
+        entry( dataArray[idx] );
+    }
+}
+
+
+function footer( /* int */ columns )
+{
+    document.write( "<tr class='content'>" );
+    document.write( "<td colspan='" + columns + "' 
class='content'>&nbsp;</th>" );
+    document.write( "</tr>" );
+
+    document.write( "</table>" );
+}
+
+
+function entry( /* Object */ dataEntry )
+{
+    document.write( "<tr id='entry" + dataEntry.id + "'>" );
+    document.write( entryInternal( dataEntry ) );
+    document.write( "</tr>" );
+
+    // dataEntry detailed properties
+    document.write( "<tr id='entry" + dataEntry.id + "_details'>" );
+    if (dataEntry.props)
+    {
+        document.write( getDataEntryDetails( dataEntry.props ) );
+    }
+    document.write( "</tr>" );
+}
+
+
+/* String */ function entryInternal( /* Object */ dataEntry )
+{
+    var id = dataEntry.id;
+    var name = dataEntry.name;
+    var state = dataEntry.state;
+    var icon = (dataEntry.props) ? "down" : "right";
+
+    var html = "<td class='content right'>" + id + "</td>";
+    html += "<td class='content'>";
+    html += "<img src='" + appRoot + "/res/imgs/" + icon + ".gif' 
onClick='showDataEntryDetails(" + id + ")' id='entry" + id + "_inline' />";
+    html += "<a href='" + pluginRoot + "/" + id + "'>" + name + "</a></td>";
+
+    html += "<td class='content center'>" + state + "</td>";
+
+    for ( var aidx in dataEntry.actions )
+    {
+        var action = dataEntry.actions[aidx];
+        html += actionButton( action.enabled, id, action.link, action.name );
+    }
+    
+    return html;
+}
+
+
+/* String */ function actionButton( /* boolean */ enabled, /* long */ id, /* 
String */ op, /* String */ opLabel )
+{
+    var theButton = "<td class='content' align='right'>";
+    if ( op )
+    {
+        theButton += "<input class='submit' type='button' value='" + opLabel + 
"'" + ( enabled ? "" : "disabled" ) + " onClick='changeDataEntryState(" + id + 
", \"" + op + "\");' />";
+    }
+    else
+    {
+        theButton += "&nbsp;";
+    }
+    theButton += "</td>";
+    return theButton;
+}
+
+
+/* String */ function getDataEntryDetails( /* Array of Object */ details )
+{
+    var innerHtml = '<td class=\"content\">&nbsp;</td><td class=\"content\" 
colspan=\"4\"><table broder=\"0\">';
+    for (var idx in details)
+    {
+        var prop = details[idx];
+        innerHtml += '<tr><td valign=\"top\" noWrap>' + prop.key + '</td><td 
valign=\"top\">' + prop.value + '</td></tr>';
+    }
+    innerHtml += '</table></td>';
+    return innerHtml;
+ }
+
+ 
+function showDetails(bundleId) {
+    var span = document.getElementById('bundle' + bundleId + '_details');
+}
+
+
+function showDataEntryDetails( id )
+{
+    var span = document.getElementById( 'entry' + id + '_details' );
+    if (span)
+    {
+        if (span.innerHTML)
+        {
+            span.innerHTML = '';
+            newLinkValue( id, appRoot + "/res/imgs/right.gif" );
+        }
+        else
+        {
+            sendRequest( 'POST', pluginRoot + '/' + id, 
displayDataEntryDetails );
+            newLinkValue( id, appRoot + "/res/imgs/down.gif" );
+        }
+    }
+}
+
+
+function newLinkValue( /* long */ id, /* String */ newLinkValue )
+{
+    
+    var link = document.getElementById( "entry" + id + "_inline" );
+    if (link)
+    {
+        link.src = newLinkValue;
+    }
+}
+
+
+function displayDataEntryDetails( obj )
+{
+    var span = document.getElementById('entry' + obj.id + '_details');
+    if (!span)
+    {
+        return;
+    }
+    
+    span.innerHTML = getDataEntryDetails( obj.props );
+}
+
+
+function changeDataEntryState(/* long */ id, /* String */ action)
+{
+    var parm = pluginRoot + "/" + id + "?action=" + action;
+    sendRequest('POST', parm, dataEntryStateChanged);
+}
+
+    
+function dataEntryStateChanged(obj)
+{
+    if (obj.reload)
+    {
+        document.location = document.location;
+    }
+    else
+    {
+        var id = obj.id;
+        if (obj.state)
+        {
+            // has status, so draw the line
+            if (obj.props)
+            {
+                var span = document.getElementById('entry' + id + '_details');
+                if (span && span.innerHTML)
+                {
+                    span.innerHTML = getDataEntryDetails( obj.props );
+                }
+                else
+                {
+                    obj.props = false;
+                }
+            }
+
+            var span = document.getElementById('entry' + id);
+            if (span)
+            {
+                span.innerHTML = entryInternal( obj );
+            }
+            
+            
+        }
+        else
+        {
+            // no status, dataEntry has been removed/uninstalled 
+            var span = document.getElementById('entry' + id);
+            if (span)
+            {
+                span.parentNode.removeChild(span);
+            }
+            var span = document.getElementById('entry' + id + '_details');
+            if (span)
+            {
+                span.parentNode.removeChild(span);
+            }
+        }
+    }    
+}
+
+    


Reply via email to