You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2014/01/10 08:29:25 UTC

svn commit: r1557045 - in /sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags: ./ impl/

Author: cziegeler
Date: Fri Jan 10 07:29:24 2014
New Revision: 1557045

URL: http://svn.apache.org/r1557045
Log:
Remove FeatureProvider interface, Features are OSGi services now - rename ProviderContext to ExecutionContext

Added:
    sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ExecutionContext.java
      - copied, changed from r1557042, sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ProviderContext.java
    sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/ExecutionContextImpl.java
      - copied, changed from r1557042, sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/ProviderContextImpl.java
Removed:
    sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/FeatureProvider.java
    sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ProviderContext.java
    sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/ProviderContextImpl.java
Modified:
    sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/Feature.java
    sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/Features.java
    sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ResourceHiding.java
    sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ResourceTypeMapping.java
    sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/ClientContextImpl.java
    sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/FeatureManager.java

Copied: sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ExecutionContext.java (from r1557042, sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ProviderContext.java)
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ExecutionContext.java?p2=sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ExecutionContext.java&p1=sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ProviderContext.java&r1=1557042&r2=1557045&rev=1557045&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ProviderContext.java (original)
+++ sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ExecutionContext.java Fri Jan 10 07:29:24 2014
@@ -25,11 +25,10 @@ import aQute.bnd.annotation.ProviderType
 
 /**
  * The provider context contains all information that is passed to a
- * {@link FeatureProvider} in order to check whether a feature
- * is enabled.
+ * {@link Feature} in order to check whether a feature is enabled.
  */
 @ProviderType
-public interface ProviderContext {
+public interface ExecutionContext {
 
     /**
      * Return the associated request if available

Modified: sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/Feature.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/Feature.java?rev=1557045&r1=1557044&r2=1557045&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/Feature.java (original)
+++ sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/Feature.java Fri Jan 10 07:29:24 2014
@@ -35,6 +35,12 @@ import aQute.bnd.annotation.ConsumerType
 public interface Feature extends Adaptable {
 
     /**
+     * Checks whether the feature is enabled for the current execution
+     * context.
+     */
+    boolean isEnabled(ExecutionContext context);
+
+    /**
      * The name of the feature.
      */
     String getName();

Modified: sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/Features.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/Features.java?rev=1557045&r1=1557044&r2=1557045&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/Features.java (original)
+++ sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/Features.java Fri Jan 10 07:29:24 2014
@@ -33,13 +33,13 @@ public interface Features {
 
     /**
      * Get the list of all available feature names. A feature is available
-     * if there is a {@link FeatureProvider}
+     * if there is a registered {@link Feature} service.
      */
     String[] getAvailableFeatureNames();
 
     /**
      * Get the list of all available features. A feature is available
-     * if there is a {@link FeatureProvider}
+     * if there is a registered {@link Feature} service.
      */
     Feature[] getAvailableFeatures();
 
@@ -51,13 +51,14 @@ public interface Features {
 
     /**
      * Checks whether a feature with the given name is available.
-     * A feature is available if there is a {@link FeatureProvider}
-     * for that feature.
+     * A feature is available if there is a registered {@link Feature} service.
      */
     boolean isAvailable(String featureName);
 
     /**
-     * Returns the current client context, if available
+     * Returns the current client context.
+     * This method always returns a client context object
+     * @return A client context.
      */
     ClientContext getCurrentClientContext();
 

Modified: sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ResourceHiding.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ResourceHiding.java?rev=1557045&r1=1557044&r2=1557045&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ResourceHiding.java (original)
+++ sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ResourceHiding.java Fri Jan 10 07:29:24 2014
@@ -31,11 +31,11 @@ public interface ResourceHiding {
 
     /**
      * Checks whether a resource should be hidden for a feature.
-     * This check is only executed if {@link FeatureProvider#isEnabled(Feature, ExecutionContext)}
+     * This check is only executed if {@link Feature#isEnabled(ExecutionContext)}
      * return true for the given feature/context. The caller of this
-     * method must ensure to call {@link FeatureProvider#isEnabled(Feature, ExecutionContext)}
+     * method must ensure to call {@link Feature#isEnabled(ExecutionContext)}
      * before calling this method and only call this method if
-     * {@link FeatureProvider#isEnabled(Feature, ExecutionContext)} returned <code>true</code>
+     * {@link Feature#isEnabled(ExecutionContext)} returned <code>true</code>
      */
     boolean hideResource(Resource resource);
 }

Modified: sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ResourceTypeMapping.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ResourceTypeMapping.java?rev=1557045&r1=1557044&r2=1557045&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ResourceTypeMapping.java (original)
+++ sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/ResourceTypeMapping.java Fri Jan 10 07:29:24 2014
@@ -31,11 +31,11 @@ public interface ResourceTypeMapping {
 
     /**
      * Returns the resource type mapping for a feature.
-     * This mapping is only executed if {@link FeatureProvider#isEnabled(Feature, ExecutionContext)}
+     * This mapping is only executed if {@link Feature#isEnabled(ExecutionContext)}
      * return true for the given feature/context. The caller of this
-     * method must ensure to call {@link FeatureProvider#isEnabled(Feature, ExecutionContext)}
+     * method must ensure to call {@link Feature#isEnabled(ExecutionContext)}
      * before calling this method and only call this method if
-     * {@link FeatureProvider#isEnabled(Feature, ExecutionContext)} returned <code>true</code>
+     * {@link Feature#isEnabled(ExecutionContext)} returned <code>true</code>
      */
     Map<String, String> getResourceTypeMapping();
 }

Modified: sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/ClientContextImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/ClientContextImpl.java?rev=1557045&r1=1557044&r2=1557045&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/ClientContextImpl.java (original)
+++ sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/ClientContextImpl.java Fri Jan 10 07:29:24 2014
@@ -27,7 +27,7 @@ import java.util.Map;
 
 import org.apache.sling.featureflags.ClientContext;
 import org.apache.sling.featureflags.Feature;
-import org.apache.sling.featureflags.ProviderContext;
+import org.apache.sling.featureflags.ExecutionContext;
 import org.apache.sling.featureflags.ResourceHiding;
 import org.apache.sling.featureflags.ResourceTypeMapping;
 
@@ -36,7 +36,7 @@ import org.apache.sling.featureflags.Res
  */
 public class ClientContextImpl implements ClientContext {
 
-    private final ProviderContext featureContext;
+    private final ExecutionContext featureContext;
 
     private final List<Feature> enabledFeatures;
 
@@ -44,7 +44,7 @@ public class ClientContextImpl implement
 
     private final Map<String, String> mapperFeatures = new HashMap<String, String>();
 
-    public ClientContextImpl(final ProviderContext featureContext, final List<Feature> features) {
+    public ClientContextImpl(final ExecutionContext featureContext, final List<Feature> features) {
         this.enabledFeatures = Collections.unmodifiableList(features);
         final List<ResourceHiding> hiding = new ArrayList<ResourceHiding>();
         for(final Feature f : this.enabledFeatures) {
@@ -62,7 +62,7 @@ public class ClientContextImpl implement
         this.featureContext = featureContext;
     }
 
-    public ProviderContext getFeatureContext() {
+    public ExecutionContext getFeatureContext() {
         return this.featureContext;
     }
 

Copied: sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/ExecutionContextImpl.java (from r1557042, sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/ProviderContextImpl.java)
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/ExecutionContextImpl.java?p2=sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/ExecutionContextImpl.java&p1=sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/ProviderContextImpl.java&r1=1557042&r2=1557045&rev=1557045&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/ProviderContextImpl.java (original)
+++ sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/ExecutionContextImpl.java Fri Jan 10 07:29:24 2014
@@ -20,23 +20,23 @@ package org.apache.sling.featureflags.im
 
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.featureflags.ProviderContext;
+import org.apache.sling.featureflags.ExecutionContext;
 
 /**
  * Implementation of the provider context.
  */
-public class ProviderContextImpl implements ProviderContext {
+public class ExecutionContextImpl implements ExecutionContext {
 
     private final ResourceResolver resourceResolver;
 
     private final SlingHttpServletRequest request;
 
-    public ProviderContextImpl(final ResourceResolver resourceResolver) {
+    public ExecutionContextImpl(final ResourceResolver resourceResolver) {
         this.request = null;
         this.resourceResolver = resourceResolver;
     }
 
-    public ProviderContextImpl(final SlingHttpServletRequest request) {
+    public ExecutionContextImpl(final SlingHttpServletRequest request) {
         this.request = request;
         this.resourceResolver = request.getResourceResolver();
     }

Modified: sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/FeatureManager.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/FeatureManager.java?rev=1557045&r1=1557044&r2=1557045&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/FeatureManager.java (original)
+++ sling/trunk/contrib/extensions/feature-flags/src/main/java/org/apache/sling/featureflags/impl/FeatureManager.java Fri Jan 10 07:29:24 2014
@@ -19,6 +19,7 @@
 package org.apache.sling.featureflags.impl;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -33,110 +34,107 @@ import org.apache.sling.api.SlingHttpSer
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.featureflags.ClientContext;
 import org.apache.sling.featureflags.Feature;
-import org.apache.sling.featureflags.FeatureProvider;
 import org.apache.sling.featureflags.Features;
-import org.apache.sling.featureflags.ProviderContext;
+import org.apache.sling.featureflags.ExecutionContext;
 import org.osgi.framework.Constants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
  * This service implements the feature handling.
- * It keeps track of all {@link FeatureProvider} services.
+ * It keeps track of all {@link Feature} services.
  */
 @Component
-@Reference(name="featureProvider",
+@Reference(name="feature",
            cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE,
            policy=ReferencePolicy.DYNAMIC,
-           referenceInterface=FeatureProvider.class)
+           referenceInterface=Feature.class)
 public class FeatureManager implements Features {
 
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
 
-    private final Map<String, List<FeatureProviderDescription>> providers = new HashMap<String, List<FeatureProviderDescription>>();
+    private final Map<String, List<FeatureDescription>> allFeatures = new HashMap<String, List<FeatureDescription>>();
 
-    private Map<String, FeatureDescription> activeProviders = new TreeMap<String, FeatureDescription>();
+    private Map<String, FeatureDescription> activeFeatures = new TreeMap<String, FeatureDescription>();
 
     /**
-     * Bind a new feature provider
+     * Bind a new feature
      */
-    protected void bindFeatureProvider(final FeatureProvider provider, final Map<String, Object> props) {
-        final Feature[] features = provider.getFeatures();
-        if ( features != null && features.length > 0 ) {
-            synchronized ( this.providers ) {
-                boolean changed = false;
-                for(final Feature f : features) {
-                    final String name = f.getName();
-                    final FeatureProviderDescription info = new FeatureProviderDescription(provider, props, f);
-
-                    List<FeatureProviderDescription> candidates = this.providers.get(name);
-                    if ( candidates == null ) {
-                        candidates = new ArrayList<FeatureProviderDescription>();
-                        this.providers.put(name, candidates);
-                    }
-                    candidates.add(info);
-                    Collections.sort(candidates);
-                    changed = true;
-                }
-                if ( changed ) {
-                    this.calculateActiveProviders();
-                }
+    protected void bindFeature(final Feature f, final Map<String, Object> props) {
+        synchronized ( this.allFeatures ) {
+            final String name = f.getName();
+            final FeatureDescription info = new FeatureDescription(f, props);
+
+            List<FeatureDescription> candidates = this.allFeatures.get(name);
+            if ( candidates == null ) {
+                candidates = new ArrayList<FeatureDescription>();
+                this.allFeatures.put(name, candidates);
             }
+            candidates.add(info);
+            Collections.sort(candidates);
+
+            this.calculateActiveProviders();
         }
     }
 
     /**
-     * Unbind a feature provider
+     * Unbind a feature
      */
-    protected void unbindFeatureProvider(final FeatureProvider provider, final Map<String, Object> props) {
-        final Feature[] features = provider.getFeatures();
-        if ( features != null && features.length > 0 ) {
-            synchronized ( this.providers ) {
-                boolean changed = false;
-                for(final Feature f : features) {
-                    final String name = f.getName();
-                    final FeatureProviderDescription info = new FeatureProviderDescription(provider, props, f);
-
-                    final List<FeatureProviderDescription> candidates = this.providers.get(name);
-                    if ( candidates != null ) { // sanity check
-                        candidates.remove(info);
-                        if ( candidates.size() == 0 ) {
-                            this.providers.remove(name);
-                            changed = true;
-                        }
-                    }
-                }
-                if ( changed ) {
-                    this.calculateActiveProviders();
+    protected void unbindFeature(final Feature f, final Map<String, Object> props) {
+        synchronized ( this.allFeatures ) {
+            final String name = f.getName();
+            final FeatureDescription info = new FeatureDescription(f, props);
+
+            final List<FeatureDescription> candidates = this.allFeatures.get(name);
+            if ( candidates != null ) { // sanity check
+                candidates.remove(info);
+                if ( candidates.size() == 0 ) {
+                    this.allFeatures.remove(name);
                 }
             }
+            this.calculateActiveProviders();
         }
     }
 
     private void calculateActiveProviders() {
         final Map<String, FeatureDescription> activeMap = new TreeMap<String, FeatureDescription>();
-        for(final Map.Entry<String, List<FeatureProviderDescription>> entry : this.providers.entrySet()) {
-            final FeatureProviderDescription desc = entry.getValue().get(0);
-            final FeatureDescription info = new FeatureDescription();
-            info.feature = desc.feature;
-            info.provider = desc.provider;
-            activeMap.put(entry.getKey(), info);
+        for(final Map.Entry<String, List<FeatureDescription>> entry : this.allFeatures.entrySet()) {
+            final FeatureDescription desc = entry.getValue().get(0);
+
+            activeMap.put(entry.getKey(), desc);
             if ( entry.getValue().size() > 1 ) {
-                logger.warn("More than one feature provider for feature {}", entry.getKey());
+                logger.warn("More than one feature service for feature {}", entry.getKey());
             }
         }
-        this.activeProviders = activeMap;
+        this.activeFeatures = activeMap;
     }
 
     private final ThreadLocal<ClientContextImpl> perThreadClientContext = new ThreadLocal<ClientContextImpl>();
 
+    private final ClientContext defaultClientContext = new ClientContext() {
+
+        @Override
+        public boolean isEnabled(final String featureName) {
+            return false;
+        }
+
+        @Override
+        public Collection<Feature> getEnabledFeatures() {
+            return Collections.emptyList();
+        }
+    };
+
     @Override
     public ClientContext getCurrentClientContext() {
-        return perThreadClientContext.get();
+        ClientContext result = perThreadClientContext.get();
+        if ( result == null ) {
+            result = defaultClientContext;
+        }
+        return result;
     }
 
     public void setCurrentClientContext(final SlingHttpServletRequest request) {
-        final ProviderContext providerContext = new ProviderContextImpl(request);
+        final ExecutionContext providerContext = new ExecutionContextImpl(request);
         final ClientContextImpl ctx = this.createClientContext(providerContext);
         perThreadClientContext.set(ctx);
     }
@@ -150,7 +148,7 @@ public class FeatureManager implements F
         if ( resolver == null ) {
             throw new IllegalArgumentException("Resolver must not be null.");
         }
-        final ProviderContext providerContext = new ProviderContextImpl(resolver);
+        final ExecutionContext providerContext = new ExecutionContextImpl(resolver);
         final ClientContext ctx = this.createClientContext(providerContext);
         return ctx;
     }
@@ -160,18 +158,18 @@ public class FeatureManager implements F
         if ( request == null ) {
             throw new IllegalArgumentException("Request must not be null.");
         }
-        final ProviderContext providerContext = new ProviderContextImpl(request);
+        final ExecutionContext providerContext = new ExecutionContextImpl(request);
         final ClientContext ctx = this.createClientContext(providerContext);
         return ctx;
     }
 
-    private ClientContextImpl createClientContext(final ProviderContext providerContext) {
+    private ClientContextImpl createClientContext(final ExecutionContext providerContext) {
         final List<Feature> enabledFeatures = new ArrayList<Feature>();
 
-        for(final Map.Entry<String, FeatureDescription> entry : this.activeProviders.entrySet()) {
+        for(final Map.Entry<String, FeatureDescription> entry : this.activeFeatures.entrySet()) {
             final Feature f = entry.getValue().feature;
 
-            if ( entry.getValue().provider.isEnabled(f, providerContext) ) {
+            if ( entry.getValue().feature.isEnabled(providerContext) ) {
                 enabledFeatures.add(f);
             }
         }
@@ -183,7 +181,7 @@ public class FeatureManager implements F
     @Override
     public Feature[] getAvailableFeatures() {
         final List<Feature> result = new ArrayList<Feature>();
-        for(final Map.Entry<String, FeatureDescription> entry : this.activeProviders.entrySet()) {
+        for(final Map.Entry<String, FeatureDescription> entry : this.activeFeatures.entrySet()) {
             final Feature f = entry.getValue().feature;
             result.add(f);
         }
@@ -192,7 +190,7 @@ public class FeatureManager implements F
 
     @Override
     public Feature getFeature(final String name) {
-        final FeatureDescription desc = this.activeProviders.get(name);
+        final FeatureDescription desc = this.activeFeatures.get(name);
         if ( desc != null ) {
             return desc.feature;
         }
@@ -201,28 +199,25 @@ public class FeatureManager implements F
 
     @Override
     public String[] getAvailableFeatureNames() {
-        return this.activeProviders.keySet().toArray(new String[this.activeProviders.size()]);
+        return this.activeFeatures.keySet().toArray(new String[this.activeFeatures.size()]);
     }
 
     @Override
     public boolean isAvailable(final String featureName) {
-        return this.activeProviders.containsKey(featureName);
+        return this.activeFeatures.containsKey(featureName);
     }
 
     /**
-     * Internal class caching some provider infos like service id and ranking.
+     * Internal class caching some feature meta data like service id and ranking.
      */
-    private final static class FeatureProviderDescription implements Comparable<FeatureProviderDescription> {
+    private final static class FeatureDescription implements Comparable<FeatureDescription> {
 
-        public final FeatureProvider provider;
         public final int ranking;
         public final long serviceId;
         public final Feature feature;
 
-        public FeatureProviderDescription(final FeatureProvider provider,
-                final Map<String, Object> props,
-                final Feature feature) {
-            this.provider = provider;
+        public FeatureDescription(final Feature feature,
+                final Map<String, Object> props) {
             this.feature = feature;
             final Object sr = props.get(Constants.SERVICE_RANKING);
             if ( sr == null || !(sr instanceof Integer)) {
@@ -234,7 +229,7 @@ public class FeatureManager implements F
         }
 
         @Override
-        public int compareTo(final FeatureProviderDescription o) {
+        public int compareTo(final FeatureDescription o) {
             if ( this.ranking < o.ranking ) {
                 return 1;
             } else if (this.ranking > o.ranking ) {
@@ -246,8 +241,8 @@ public class FeatureManager implements F
 
         @Override
         public boolean equals(final Object obj) {
-            if ( obj instanceof FeatureProviderDescription ) {
-                return ((FeatureProviderDescription)obj).serviceId == this.serviceId;
+            if ( obj instanceof FeatureDescription ) {
+                return ((FeatureDescription)obj).serviceId == this.serviceId;
             }
             return false;
         }
@@ -260,10 +255,4 @@ public class FeatureManager implements F
             return result;
         }
     }
-
-    private final static class FeatureDescription {
-        public Feature feature;
-        public FeatureProvider provider;
-
-    }
 }