You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by gn...@apache.org on 2009/08/11 22:10:59 UTC

svn commit: r803273 - in /felix/trunk/karaf: assembly/src/main/filtered-resources/ deployer/features/src/main/java/org/apache/felix/karaf/deployer/features/ features/command/src/main/java/org/apache/felix/karaf/features/command/ features/core/src/main/...

Author: gnodet
Date: Tue Aug 11 20:10:59 2009
New Revision: 803273

URL: http://svn.apache.org/viewvc?rev=803273&view=rev
Log:
FELIX-1127: Add a name for a repository

Added:
    felix/trunk/karaf/webconsole/features/src/main/java/org/apache/felix/karaf/webconsole/features/ExtendedFeature.java
Removed:
    felix/trunk/karaf/webconsole/features/src/main/java/org/apache/felix/karaf/webconsole/features/Feature.java
Modified:
    felix/trunk/karaf/assembly/src/main/filtered-resources/features.xml
    felix/trunk/karaf/deployer/features/src/main/java/org/apache/felix/karaf/deployer/features/FeatureDeploymentListener.java
    felix/trunk/karaf/features/command/src/main/java/org/apache/felix/karaf/features/command/ListFeaturesCommand.java
    felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/Repository.java
    felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/internal/RepositoryImpl.java
    felix/trunk/karaf/features/management/src/main/java/org/apache/felix/karaf/features/management/FeaturesServiceMBean.java
    felix/trunk/karaf/features/management/src/main/java/org/apache/felix/karaf/features/management/codec/JmxRepository.java
    felix/trunk/karaf/features/management/src/main/java/org/apache/felix/karaf/features/management/codec/JmxRepositoryEvent.java
    felix/trunk/karaf/webconsole/features/src/main/java/org/apache/felix/karaf/webconsole/features/FeaturesPlugin.java
    felix/trunk/karaf/webconsole/features/src/main/resources/res/ui/features.js

Modified: felix/trunk/karaf/assembly/src/main/filtered-resources/features.xml
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/assembly/src/main/filtered-resources/features.xml?rev=803273&r1=803272&r2=803273&view=diff
==============================================================================
--- felix/trunk/karaf/assembly/src/main/filtered-resources/features.xml (original)
+++ felix/trunk/karaf/assembly/src/main/filtered-resources/features.xml Tue Aug 11 20:10:59 2009
@@ -16,7 +16,7 @@
       See the License for the specific language governing permissions and
       limitations under the License.
 -->
-<features>
+<features name="default}">
     <feature name="spring" version="${spring.version}">
         <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/${aopalliance.version}</bundle>
         <bundle>mvn:org.springframework/spring-core/${spring.version}</bundle>

Modified: felix/trunk/karaf/deployer/features/src/main/java/org/apache/felix/karaf/deployer/features/FeatureDeploymentListener.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/deployer/features/src/main/java/org/apache/felix/karaf/deployer/features/FeatureDeploymentListener.java?rev=803273&r1=803272&r2=803273&view=diff
==============================================================================
--- felix/trunk/karaf/deployer/features/src/main/java/org/apache/felix/karaf/deployer/features/FeatureDeploymentListener.java (original)
+++ felix/trunk/karaf/deployer/features/src/main/java/org/apache/felix/karaf/deployer/features/FeatureDeploymentListener.java Tue Aug 11 20:10:59 2009
@@ -166,21 +166,27 @@
                     for (Repository repo : featuresService.listRepositories()) {
                         if (repo.getURI().equals(url.toURI())) {
                             for (Feature f : repo.getFeatures()) {
-                                featuresService.installFeature(f.getName(), f.getVersion());
+                                try {
+                                    featuresService.installFeature(f.getName(), f.getVersion());
+                                } catch (Exception e) {
+                                    LOGGER.error("Unable to install feature: " + f.getName(), e);
+                                }
                             }
                         }
                     }
-                    featuresService.removeRepository(url.toURI());
                 }
             } else if (bundleEvent.getType() == BundleEvent.UNINSTALLED) {
                 Enumeration featuresUrlEnumeration = bundle.findEntries("/META-INF/" + FEATURE_PATH + "/", "*.xml", false);
                 while (featuresUrlEnumeration != null && featuresUrlEnumeration.hasMoreElements()) {
                     URL url = (URL) featuresUrlEnumeration.nextElement();
-                    featuresService.addRepository(url.toURI());
                     for (Repository repo : featuresService.listRepositories()) {
                         if (repo.getURI().equals(url.toURI())) {
                             for (Feature f : repo.getFeatures()) {
-                                featuresService.uninstallFeature(f.getName(), f.getVersion());
+                                try {
+                                    featuresService.uninstallFeature(f.getName(), f.getVersion());
+                                } catch (Exception e) {
+                                    LOGGER.error("Unable to uninstall feature: " + f.getName(), e);
+                                }
                             }
                         }
                     }

Modified: felix/trunk/karaf/features/command/src/main/java/org/apache/felix/karaf/features/command/ListFeaturesCommand.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/features/command/src/main/java/org/apache/felix/karaf/features/command/ListFeaturesCommand.java?rev=803273&r1=803272&r2=803273&view=diff
==============================================================================
--- felix/trunk/karaf/features/command/src/main/java/org/apache/felix/karaf/features/command/ListFeaturesCommand.java (original)
+++ felix/trunk/karaf/features/command/src/main/java/org/apache/felix/karaf/features/command/ListFeaturesCommand.java Tue Aug 11 20:10:59 2009
@@ -17,10 +17,14 @@
 package org.apache.felix.karaf.features.command;
 
 import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.felix.karaf.features.FeaturesService;
 import org.apache.felix.karaf.features.Feature;
+import org.apache.felix.karaf.features.Repository;
 import org.apache.felix.gogo.commands.Option;
 import org.apache.felix.gogo.commands.Command;
 
@@ -30,53 +34,90 @@
     @Option(name = "-i", aliases={"--installed"}, description="Display the list of installed features")
     boolean installed;
 
+    private static final String STATE = "State";
+    private static final String INSTALLED = "installed  ";
+    private static final String UNINSTALLED = "uninstalled";
+
+    private static final String VERSION = "Version";
+    private static final String NAME = "Name";
+    private static final String REPOSITORY = "Repository";
+
     protected void doExecute(FeaturesService admin) throws Exception {
-        List<Feature> features;
-        List<Feature> installedFeatures;
-        if (installed) {
-            features = Arrays.asList(admin.listInstalledFeatures());
-            installedFeatures = features;
-            if (features == null || features.size() == 0) {
+
+        // Get the feature data to print.
+        List<Feature> features = new ArrayList<Feature>();
+        Map<Feature, String> repositoryNames = new HashMap<Feature, String>();
+        for (Repository r : Arrays.asList(admin.listRepositories())) {
+            for (Feature f : r.getFeatures()) {
+                if (installed && !admin.isInstalled(f)) {
+                    continue;
+                }
+                features.add(f);
+                repositoryNames.put(f, r.getName());
+            }
+        }
+        if (features.size() == 0) {
+            if (installed) {
                 System.out.println("No features installed.");
-                return;
             }
-        } else {
-            features = Arrays.asList(admin.listFeatures());
-            installedFeatures = Arrays.asList(admin.listInstalledFeatures());
-            if (features == null || features.size() == 0) {
+            else {
                 System.out.println("No features available.");
-                return;
             }
+            return;
         }
-        int maxVersionSize = 7;
-        for (Feature feature : features) {
-            maxVersionSize = Math.max(maxVersionSize, feature.getVersion().length());
+
+        // Print column headers.
+        int maxVersionSize = VERSION.length();
+        for (Feature f : features) {
+            maxVersionSize = Math.max(maxVersionSize, f.getVersion().length());
+        }
+        int maxNameSize = NAME.length();
+        for (Feature f : features) {
+            maxNameSize = Math.max(maxNameSize, f.getName().length());
         }
         StringBuilder sb = new StringBuilder();
-        sb.append("  State         Version    ");
-        for (int i = 7; i < maxVersionSize; i++) {
+        sb.append(STATE).append("         ").append(VERSION).append("   ");
+        for (int i = VERSION.length(); i < maxVersionSize; i++) {
+            sb.append(" ");
+        }
+        sb.append(NAME).append(" ");
+        for (int i = NAME.length(); i < maxNameSize; i++) {
             sb.append(" ");
         }
-        sb.append("Name");
+        sb.append(REPOSITORY);
         System.out.println(sb.toString());
-        for (Feature feature : features) {
+
+        // Print the feature data.
+        for (Feature f : features) {
+
             sb.setLength(0);
             sb.append("[");
-            if (installedFeatures.contains(feature)) {
-                sb.append("installed  ");
+            if (admin.isInstalled(f)) {
+                sb.append(INSTALLED);
             } else {
-                sb.append("uninstalled");
+                sb.append(UNINSTALLED);
             }
+
             sb.append("] [");
-            String v = feature.getVersion();
-            sb.append(v);
-            for (int i = v.length(); i < maxVersionSize; i++) {
+            String str = f.getVersion();
+            sb.append(str);
+            for (int i = str.length(); i < maxVersionSize; i++) {
                 sb.append(" ");
             }
             sb.append("] ");
-            sb.append(feature.getName());
+
+            str = f.getName();
+            sb.append(str);
+            for (int i = str.length(); i < maxNameSize; i++) {
+                sb.append(" ");
+            }
+
+            sb.append(" ");
+            sb.append(repositoryNames.get(f));
             System.out.println(sb.toString());
+
         }
+
     }
 
 }

Modified: felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/Repository.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/Repository.java?rev=803273&r1=803272&r2=803273&view=diff
==============================================================================
--- felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/Repository.java (original)
+++ felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/Repository.java Tue Aug 11 20:10:59 2009
@@ -23,6 +23,8 @@
  */
 public interface Repository {
 
+    String getName();
+
     URI getURI();
 
     URI[] getRepositories() throws Exception;

Modified: felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/internal/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/internal/RepositoryImpl.java?rev=803273&r1=803272&r2=803273&view=diff
==============================================================================
--- felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/internal/RepositoryImpl.java (original)
+++ felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/internal/RepositoryImpl.java Tue Aug 11 20:10:59 2009
@@ -47,6 +47,8 @@
  */
 public class RepositoryImpl implements Repository {
 
+    private int unnamedRepoId = 0;
+    private String name;
     private URI uri;
     private List<Feature> features;
     private List<URI> repositories;
@@ -55,6 +57,10 @@
         this.uri = uri;
     }
 
+    public String getName() {
+        return name;
+    }
+
     public URI getURI() {
         return uri;
     }
@@ -81,6 +87,16 @@
             URLConnection conn = uri.toURL().openConnection();
             conn.setDefaultUseCaches(false);
             Document doc = factory.newDocumentBuilder().parse(conn.getInputStream());
+            String temp = doc.getDocumentElement().getAttribute( "name" );
+            if ("".equals(temp)) {
+                name = "repo-" + String.valueOf(unnamedRepoId++);
+            }
+            else {
+                name = temp;
+            }
+            if ( uri.toString().startsWith( "bundle" ) ) {
+                name += "*";
+            }
             
             NodeList nodes = doc.getDocumentElement().getChildNodes();
             for (int i = 0; i < nodes.getLength(); i++) {

Modified: felix/trunk/karaf/features/management/src/main/java/org/apache/felix/karaf/features/management/FeaturesServiceMBean.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/features/management/src/main/java/org/apache/felix/karaf/features/management/FeaturesServiceMBean.java?rev=803273&r1=803272&r2=803273&view=diff
==============================================================================
--- felix/trunk/karaf/features/management/src/main/java/org/apache/felix/karaf/features/management/FeaturesServiceMBean.java (original)
+++ felix/trunk/karaf/features/management/src/main/java/org/apache/felix/karaf/features/management/FeaturesServiceMBean.java Tue Aug 11 20:10:59 2009
@@ -83,6 +83,8 @@
     String[] FEATURE_EVENT = { FEATURE_NAME, FEATURE_VERSION, FEATURE_EVENT_EVENT_TYPE };
 
 
+    String REPOSITORY_NAME = "Name";
+
     String REPOSITORY_URI = "Uri";
 
     String REPOSITORY_REPOSITORIES = "Repositories";
@@ -103,12 +105,12 @@
     /**
      * The item names in the CompositeData representing a feature
      */
-    String[] REPOSITORY = { REPOSITORY_URI,  REPOSITORY_REPOSITORIES, REPOSITORY_FEATURES };
+    String[] REPOSITORY = { REPOSITORY_NAME, REPOSITORY_URI,  REPOSITORY_REPOSITORIES, REPOSITORY_FEATURES };
 
     /**
      * The item names in the CompositeData representing the event raised for
      * feature events within the OSGi container by this bean
      */
-    String[] REPOSITORY_EVENT = { REPOSITORY_URI, REPOSITORY_EVENT_EVENT_TYPE };
+    String[] REPOSITORY_EVENT = { REPOSITORY_NAME, REPOSITORY_URI, REPOSITORY_EVENT_EVENT_TYPE };
 
 }

Modified: felix/trunk/karaf/features/management/src/main/java/org/apache/felix/karaf/features/management/codec/JmxRepository.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/features/management/src/main/java/org/apache/felix/karaf/features/management/codec/JmxRepository.java?rev=803273&r1=803272&r2=803273&view=diff
==============================================================================
--- felix/trunk/karaf/features/management/src/main/java/org/apache/felix/karaf/features/management/codec/JmxRepository.java (original)
+++ felix/trunk/karaf/features/management/src/main/java/org/apache/felix/karaf/features/management/codec/JmxRepository.java Tue Aug 11 20:10:59 2009
@@ -46,9 +46,10 @@
         try {
             String[] itemNames = FeaturesServiceMBean.REPOSITORY;
             Object[] itemValues = new Object[itemNames.length];
-            itemValues[0] = repository.getURI().toString();
-            itemValues[1] = toStringArray(repository.getRepositories());
-            itemValues[2] = JmxFeature.getFeatureIdentifierTable(Arrays.asList(repository.getFeatures()));
+            itemValues[0] = repository.getName();
+            itemValues[1] = repository.getURI().toString();
+            itemValues[2] = toStringArray(repository.getRepositories());
+            itemValues[3] = JmxFeature.getFeatureIdentifierTable(Arrays.asList(repository.getFeatures()));
             data = new CompositeDataSupport(REPOSITORY, itemNames, itemValues);
         } catch (Exception e) {
             throw new IllegalStateException("Cannot form repository open data", e);
@@ -90,12 +91,14 @@
             OpenType[] itemTypes = new OpenType[itemNames.length];
             String[] itemDescriptions = new String[itemNames.length];
             itemTypes[0] = SimpleType.STRING;
-            itemTypes[1] = new ArrayType(1, SimpleType.STRING);
-            itemTypes[2] = JmxFeature.FEATURE_IDENTIFIER_TABLE;
-
-            itemDescriptions[0] = "The uri of the repository";
-            itemDescriptions[1] = "The dependent repositories";
-            itemDescriptions[2] = "The list of included features";
+            itemTypes[1] = SimpleType.STRING;
+            itemTypes[2] = new ArrayType(1, SimpleType.STRING);
+            itemTypes[3] = JmxFeature.FEATURE_IDENTIFIER_TABLE;
+
+            itemDescriptions[0] = "The name of the repository";
+            itemDescriptions[1] = "The uri of the repository";
+            itemDescriptions[2] = "The dependent repositories";
+            itemDescriptions[3] = "The list of included features";
 
             return new CompositeType("Repository", description, itemNames,
                     itemDescriptions, itemTypes);

Modified: felix/trunk/karaf/features/management/src/main/java/org/apache/felix/karaf/features/management/codec/JmxRepositoryEvent.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/features/management/src/main/java/org/apache/felix/karaf/features/management/codec/JmxRepositoryEvent.java?rev=803273&r1=803272&r2=803273&view=diff
==============================================================================
--- felix/trunk/karaf/features/management/src/main/java/org/apache/felix/karaf/features/management/codec/JmxRepositoryEvent.java (original)
+++ felix/trunk/karaf/features/management/src/main/java/org/apache/felix/karaf/features/management/codec/JmxRepositoryEvent.java Tue Aug 11 20:10:59 2009
@@ -36,7 +36,8 @@
         try {
             String[] itemNames = FeaturesServiceMBean.REPOSITORY_EVENT;
             Object[] itemValues = new Object[itemNames.length];
-            itemValues[0] = event.getRepository().getURI().toString();
+            itemValues[0] = event.getRepository().getName();
+            itemValues[1] = event.getRepository().getURI().toString();
             switch (event.getType()) {
                 case RepositoryAdded:   itemValues[2] = FeaturesServiceMBean.REPOSITORY_EVENT_EVENT_TYPE_ADDED; break;
                 case RepositoryRemoved: itemValues[2] = FeaturesServiceMBean.REPOSITORY_EVENT_EVENT_TYPE_REMOVED; break;
@@ -64,9 +65,11 @@
             String[] itemDescriptions = new String[itemNames.length];
             itemTypes[0] = SimpleType.STRING;
             itemTypes[1] = SimpleType.STRING;
+            itemTypes[2] = SimpleType.STRING;
 
-            itemDescriptions[0] = "The uri of the repository";
-            itemDescriptions[1] = "The type of event";
+            itemDescriptions[0] = "The name of the repository";
+            itemDescriptions[1] = "The uri of the repository";
+            itemDescriptions[2] = "The type of event";
 
             return new CompositeType("RepositoryEvent", description, itemNames,
                     itemDescriptions, itemTypes);

Added: felix/trunk/karaf/webconsole/features/src/main/java/org/apache/felix/karaf/webconsole/features/ExtendedFeature.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/webconsole/features/src/main/java/org/apache/felix/karaf/webconsole/features/ExtendedFeature.java?rev=803273&view=auto
==============================================================================
--- felix/trunk/karaf/webconsole/features/src/main/java/org/apache/felix/karaf/webconsole/features/ExtendedFeature.java (added)
+++ felix/trunk/karaf/webconsole/features/src/main/java/org/apache/felix/karaf/webconsole/features/ExtendedFeature.java Tue Aug 11 20:10:59 2009
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+package org.apache.felix.karaf.webconsole.features;
+
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.karaf.features.Feature;
+
+
+/**
+ * 
+ */
+public class ExtendedFeature implements Feature
+{
+
+    public enum State
+    {
+        INSTALLED, UNINSTALLED;
+
+        @Override
+        public String toString()
+        {
+            //only capitalize the first letter
+            String s = super.toString();
+            return s.substring( 0, 1 ) + s.substring( 1 ).toLowerCase();
+        }
+    };
+
+    protected State state;
+    protected String repository;
+    protected Feature feature;
+
+
+    //
+    // Constructors
+    //
+
+    public ExtendedFeature( State state, String repository, Feature feature )
+    {
+        this.state = state;
+        this.repository = repository;
+        this.feature = feature;
+    }
+
+
+    //
+    // Feature interface
+    //
+
+
+    public List<String> getBundles()
+    {
+        return this.feature.getBundles();
+    }
+
+
+    public Map<String, Map<String, String>> getConfigurations()
+    {
+        return this.feature.getConfigurations();
+    }
+
+
+    public List<Feature> getDependencies()
+    {
+        return this.feature.getDependencies();
+    }
+
+
+    public String getId()
+    {
+        return this.feature.getId();
+    }
+
+
+    public String getName()
+    {
+        return this.feature.getName();
+    }
+
+
+    public String getVersion()
+    {
+        return this.feature.getVersion();
+    }
+
+
+    //
+    // Additional methods
+    //
+
+
+    public String getRepository() {
+        return this.repository;
+    }
+
+
+    public State getState() {
+        return this.state;
+    }
+}

Modified: felix/trunk/karaf/webconsole/features/src/main/java/org/apache/felix/karaf/webconsole/features/FeaturesPlugin.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/webconsole/features/src/main/java/org/apache/felix/karaf/webconsole/features/FeaturesPlugin.java?rev=803273&r1=803272&r2=803273&view=diff
==============================================================================
--- felix/trunk/karaf/webconsole/features/src/main/java/org/apache/felix/karaf/webconsole/features/FeaturesPlugin.java (original)
+++ felix/trunk/karaf/webconsole/features/src/main/java/org/apache/felix/karaf/webconsole/features/FeaturesPlugin.java Tue Aug 11 20:10:59 2009
@@ -22,9 +22,13 @@
 import java.io.PrintWriter;
 import java.net.URI;
 import java.net.URL;
-import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Properties;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
@@ -32,8 +36,10 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.felix.karaf.features.Feature;
+import org.apache.felix.karaf.features.FeaturesService;
+import org.apache.felix.karaf.features.Repository;
 import org.apache.felix.webconsole.AbstractWebConsolePlugin;
-import org.apache.felix.karaf.features.*;
 
 import org.json.JSONException;
 import org.json.JSONWriter;
@@ -65,9 +71,9 @@
     private BundleContext bundleContext;
 
 
-    /*
-     * Blueprint lifecycle callback methods
-     */
+    //
+    // Blueprint lifecycle callback methods
+    //
     
     public void start()
     {
@@ -78,15 +84,18 @@
         this.log.info( LABEL + " plugin activated" );
     }
 
+
     public void stop()
     {
         this.log.info( LABEL + " plugin deactivated" );
         super.deactivate();
     }
 
+
     //
     // AbstractWebConsolePlugin interface
-    //    
+    //
+
     public String getLabel()
     {
         return NAME;
@@ -316,9 +325,9 @@
 
     private void writeJSON( final PrintWriter pw ) throws IOException
     {
-        final Feature[] features = this.getFeatures();
+        final List<Repository> repositories = this.getRepositories();
+        final List<ExtendedFeature> features = this.getFeatures( repositories );
         final String statusLine = this.getStatusLine( features );
-        final String[] repositories = this.getRepositories();
 
         final JSONWriter jw = new JSONWriter( pw );
 
@@ -329,30 +338,37 @@
             jw.key( "status" );
             jw.value( statusLine );
 
-            jw.key( "features" );
-            jw.array();
-            for ( int i = 0; i < features.length; i++ )
-            {
-                featureInfo( jw, features[i] );
-            }
-            jw.endArray();
-
             jw.key( "repositories" );
             jw.array();
-            for ( int i = 0; i < repositories.length; i++ )
+            for ( Repository r : repositories )
             {
                 jw.object();
+                jw.key( "name" );
+                jw.value( r.getName() );
                 jw.key( "url" );
-                jw.value( repositories[i] );
+                String uri = r.getURI().toString();
+                jw.value( uri );
                 jw.key( "actions" );
                 jw.array();
-                action( jw, true, "refreshRepository", "Refresh", "refresh" );
-                action( jw, true, "removeRepository", "Uninstall", "delete" );
+                boolean enable = true;
+                if ( uri.startsWith( "bundle" ) ) {
+                    enable = false;
+                }
+                action( jw, enable, "refreshRepository", "Refresh", "refresh" );
+                action( jw, enable, "removeRepository", "Remove", "delete" );
                 jw.endArray();
                 jw.endObject();
             }
             jw.endArray();
 
+            jw.key( "features" );
+            jw.array();
+            for ( ExtendedFeature f : features )
+            {
+                featureInfo( jw, f );
+            }
+            jw.endArray();
+
             jw.endObject();
 
         }
@@ -364,9 +380,9 @@
     }
 
 
-    private String[] getRepositories()
+    private List<Repository> getRepositories()
     {
-        String[] repositories = new String[0];
+        List<Repository> repositories = new ArrayList<Repository>();
 
         if ( featuresService == null )
         {
@@ -374,29 +390,24 @@
             return repositories;
         }
 
-        Repository[] repositoryInfo = null;
         try
         {
-            repositoryInfo = featuresService.listRepositories();
+            for ( Repository r : featuresService.listRepositories() ) {
+                repositories.add( r );
+            }
         }
         catch ( Exception e )
         {
             this.log.error( e.getMessage() );
-            return new String[0];
         }
 
-        repositories = new String[repositoryInfo.length];
-        for ( int i = 0; i < repositoryInfo.length; i++ )
-        {
-            repositories[i] = repositoryInfo[i].getURI().toString();
-        }
         return repositories;
     }
 
 
-    private Feature[] getFeatures()
+    private List<ExtendedFeature> getFeatures( List<Repository> repositories )
     {
-        Feature[] features = new Feature[0];
+        List<ExtendedFeature> features = new ArrayList<ExtendedFeature>();
 
         if ( featuresService == null )
         {
@@ -404,60 +415,54 @@
             return features;
         }
 
-        List<org.apache.felix.karaf.features.Feature> allFeatures = null;
-        List<org.apache.felix.karaf.features.Feature> installedFeatures = null;
         try
         {
-            allFeatures = Arrays.asList(featuresService.listFeatures());
-            installedFeatures = Arrays.asList(featuresService.listInstalledFeatures());
+            for ( Repository r : repositories )
+            {
+                for ( Feature f : r.getFeatures() )
+                {
+                    ExtendedFeature.State state =
+                        featuresService.isInstalled(f) ? ExtendedFeature.State.INSTALLED : ExtendedFeature.State.UNINSTALLED;
+                    features.add( new ExtendedFeature(  state, r.getName(), f ) );
+                }
+            }
         }
         catch ( Exception e )
         {
             this.log.error( e.getMessage() );
-            return new Feature[0];
         }
 
-        features = new Feature[allFeatures.size()];
-        for ( int i = 0; i < features.length; i++ )
-        {
-            Feature.State state = Feature.State.UNINSTALLED;
-            if ( installedFeatures.contains( allFeatures.get(i) ) )
-            {
-                state = Feature.State.INSTALLED;
-            }
-            features[i] = new Feature( allFeatures.get(i).getName(), allFeatures.get(i).getVersion(), state );
-        }
-        Arrays.sort( features, new FeatureComparator() );
+        Collections.sort( features, new ExtendedFeatureComparator() );
         return features;
     }
 
 
-    class FeatureComparator implements Comparator<Feature>
+    class ExtendedFeatureComparator implements Comparator<ExtendedFeature>
     {
-        public int compare( Feature o1, Feature o2 )
+        public int compare( ExtendedFeature o1, ExtendedFeature o2 )
         {
-            return o1.name.toLowerCase().compareTo( o2.name.toLowerCase() );
+            return o1.getName().toLowerCase().compareTo( o2.getName().toLowerCase() );
         }
     }
 
 
-    private String getStatusLine( final Feature[] features )
+    private String getStatusLine( final List<ExtendedFeature> features )
     {
         int installed = 0;
-        for ( int i = 0; i < features.length; i++ )
+        for ( ExtendedFeature f : features )
         {
-            if ( features[i].state == Feature.State.INSTALLED )
+            if ( f.getState() == ExtendedFeature.State.INSTALLED )
             {
                 installed++;
             }
         }
         final StringBuffer buffer = new StringBuffer();
         buffer.append( "Feature information: " );
-        appendFeatureInfoCount( buffer, "in total", features.length );
-        if ( installed == features.length )
+        appendFeatureInfoCount( buffer, "in total", features.size() );
+        if ( installed == features.size() )
         {
             buffer.append( " - all " );
-            appendFeatureInfoCount( buffer, "active.", features.length );
+            appendFeatureInfoCount( buffer, "active.", features.size() );
         }
         else
         {
@@ -483,24 +488,29 @@
     }
 
 
-    private void featureInfo( JSONWriter jw, Feature feature ) throws JSONException
+    private void featureInfo( JSONWriter jw, ExtendedFeature feature ) throws JSONException
     {
         jw.object();
+        jw.key( "id" );
+        jw.value( feature.getId() );
         jw.key( "name" );
-        jw.value( feature.name );
+        jw.value( feature.getName() );
         jw.key( "version" );
-        jw.value( feature.version );
+        jw.value( feature.getVersion() );
+        jw.key( "repository" );
+        jw.value( feature.getRepository() );
         jw.key( "state" );
-        jw.value( feature.state );
+        ExtendedFeature.State state = feature.getState();
+        jw.value( state.toString() );
 
         jw.key( "actions" );
         jw.array();
 
-        if ( feature.state == Feature.State.INSTALLED )
+        if ( state == ExtendedFeature.State.INSTALLED )
         {
             action( jw, true, "uninstallFeature", "Uninstall", "delete" );
         }
-        else
+        else if ( state == ExtendedFeature.State.UNINSTALLED )
         {
             action( jw, true, "installFeature", "Install", "start" );
         }
@@ -519,13 +529,18 @@
         jw.key( "image" ).value( image );
         jw.endObject();
     }
-    
-    // DI setters
+
+
+    //
+    // Dependency Injection setters
+    //
+
     public void setFeaturesService(FeaturesService featuresService) 
     {
         this.featuresService = featuresService;
     }
-    
+
+
     public void setBundleContext(BundleContext bundleContext) 
     {
         this.bundleContext = bundleContext;

Modified: felix/trunk/karaf/webconsole/features/src/main/resources/res/ui/features.js
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/webconsole/features/src/main/resources/res/ui/features.js?rev=803273&r1=803272&r2=803273&view=diff
==============================================================================
--- felix/trunk/karaf/webconsole/features/src/main/resources/res/ui/features.js (original)
+++ felix/trunk/karaf/webconsole/features/src/main/resources/res/ui/features.js Tue Aug 11 20:10:59 2009
@@ -19,31 +19,19 @@
     $(document).ready( function() {
         renderView();
         renderData( data );
-        $("#repository_table").tablesorter( {
-            headers: {
-                1: { sorter: false }
-            },
-            sortList: [[0,0]],
-        } );
-        $("#feature_table").tablesorter( {
-            headers: {
-                3: { sorter: false }
-            },
-            sortList: [[0,0]],
-        } );
     } );
 }
 
 function renderView() {
     renderStatusLine();
-    renderTable( "Feature Repositories", "repository_table", ["URL", "Actions"] );
+    renderTable( "Feature Repositories", "repository_table", ["Name", "URL", "Actions"] );
     var txt = "<form method='post'><div class='table'><table class='tablelayout'><tbody><tr>" +
         "<input type='hidden' name='action' value='addRepository'/>" +
         "<td><input id='url' type='text' name='url' style='width:100%'/></td>" +
-        "<td class='col_Actions'><input type='button' value='Add URL' onclick='addRepositoryUrl()'/></td>" +
+        "<td class='col_Actions'><input type='button' value='Add URL' onclick='addRepositoryUrl()' colspan='2'/></td>" +
         "</tr></tbody></table></div></form><br/>";
     $("#plugin_content").append( txt );
-    renderTable( "Features", "feature_table", ["Name", "Version", "Status", "Actions"] );
+    renderTable( "Features", "feature_table", ["Name", "Version", "Repository", "Status", "Actions"] );
     renderStatusLine();
 }
 
@@ -72,6 +60,18 @@
     renderStatusData( data.status );
     renderRepositoryTableData( data.repositories );
     renderFeatureTableData( data.features );
+    $("#repository_table").tablesorter( {
+        headers: {
+            2: { sorter: false }
+        },
+        sortList: [[0,0]],
+    } );
+    $("#feature_table").tablesorter( {
+        headers: {
+           4: { sorter: false }
+        },
+        sortList: [[0,0]],
+    } );
 }
 
 function renderStatusData( /* String */ status )  {
@@ -83,7 +83,7 @@
     var input;
     $("#repository_table > tbody > tr").remove();
     for ( var idx in repositories ) {
-        trElement = tr( null, { id: "repository-" + idx } );
+        trElement = tr( null, { id: "repository-" + repositories[idx].name } );
         renderRepositoryData( trElement, repositories[idx] );
         $("#repository_table > tbody").append( trElement ); 
     }
@@ -91,6 +91,7 @@
 }
 
 function renderRepositoryData( /* Element */ parent, /* Object */ repository ) {
+    parent.appendChild( td( null, null, [text( repository.name )] ) );
     parent.appendChild( td( null, null, [text( repository.url )] ) );
 
     var actionsTd = td( null, null );
@@ -134,7 +135,7 @@
 function renderFeatureTableData( /* array of Objects */ features ) {
     $("#feature_table > tbody > tr").remove();
     for ( var idx in features ) {
-        var trElement = tr( null, { id: "feature-" + idx } );
+        var trElement = tr( null, { id: "feature-" + features[idx].id } );
         renderFeatureData( trElement, features[idx] );
         $("#feature_table > tbody").append( trElement ); 
     }
@@ -144,6 +145,7 @@
 function renderFeatureData( /* Element */ parent, /* Object */ feature ) {
     parent.appendChild( td( null, null, [ text( feature.name ) ] ) );
     parent.appendChild( td( null, null, [ text( feature.version ) ] ) );
+    parent.appendChild( td( null, null, [ text( feature.repository ) ] ) );
     parent.appendChild( td( null, null, [ text( feature.state ) ] ) );
     var actionsTd = td( null, null );
     var div = createElement( "div", null, {