You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:34:21 UTC

[sling-org-apache-sling-featureflags] 02/25: Implemet hiding of resource and decorating

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.featureflags-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-featureflags.git

commit 68ee64644cd4597f0bf5b904c40a7a7dfb5e1dac
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Thu Dec 19 03:46:14 2013 +0000

    Implemet hiding of resource and decorating
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/whiteboard/feature-flags@1552222 13f79535-47bb-0310-9956-ffa450edef68
---
 .../featureflags/impl/ExecutionContextFilter.java  |   8 +-
 .../extensions/featureflags/impl/FeatureImpl.java  | 154 +--------------------
 .../impl/{FeatureImpl.java => FeatureManager.java} |  32 ++++-
 .../featureflags/impl/ResourceAccessImpl.java      |   9 +-
 ...eAccessImpl.java => ResourceDecoratorImpl.java} |  45 ++++--
 5 files changed, 75 insertions(+), 173 deletions(-)

diff --git a/src/main/java/org/apache/sling/extensions/featureflags/impl/ExecutionContextFilter.java b/src/main/java/org/apache/sling/extensions/featureflags/impl/ExecutionContextFilter.java
index 7ee7b85..8103bc4 100644
--- a/src/main/java/org/apache/sling/extensions/featureflags/impl/ExecutionContextFilter.java
+++ b/src/main/java/org/apache/sling/extensions/featureflags/impl/ExecutionContextFilter.java
@@ -19,8 +19,9 @@
 package org.apache.sling.extensions.featureflags.impl;
 
 import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
@@ -85,7 +86,7 @@ public class ExecutionContextFilter implements Filter {
     public final class ExecutionContextInfo {
 
         public final ExecutionContext context;
-        public final Set<String> enabledFeatures = new HashSet<String>();
+        public final List<String> enabledFeatures = new ArrayList<String>();
 
         public ExecutionContextInfo(final SlingHttpServletRequest req,
                 final Feature feature) {
@@ -95,6 +96,7 @@ public class ExecutionContextFilter implements Filter {
                     enabledFeatures.add(name);
                 }
             }
+            Collections.sort(enabledFeatures);
         }
     }
 }
diff --git a/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureImpl.java b/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureImpl.java
index 65abe86..b42dca9 100644
--- a/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureImpl.java
+++ b/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureImpl.java
@@ -18,21 +18,12 @@
  */
 package org.apache.sling.extensions.featureflags.impl;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.ReferencePolicy;
 import org.apache.felix.scr.annotations.Service;
 import org.apache.sling.extensions.featureflags.ExecutionContext;
 import org.apache.sling.extensions.featureflags.Feature;
 import org.apache.sling.extensions.featureflags.FeatureProvider;
-import org.osgi.framework.Constants;
 
 /**
  * This service implements the feature handling.
@@ -40,157 +31,24 @@ import org.osgi.framework.Constants;
  */
 @Component
 @Service(value=Feature.class)
-@Reference(name="featureProvider",
-           cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE,
-           policy=ReferencePolicy.DYNAMIC,
-           referenceInterface=FeatureProvider.class)
 public class FeatureImpl implements Feature {
 
-    private final Map<String, List<FeatureProviderDescription>> providers = new HashMap<String, List<FeatureProviderDescription>>();
-
-    private Map<String, FeatureProviderDescription> activeProviders = new HashMap<String, FeatureProviderDescription>();
-
-    /**
-     * Bind a new feature provider
-     */
-    protected void bindFeatureProvider(final FeatureProvider provider, final Map<String, Object> props) {
-        final String[] features = provider.getFeatureNames();
-        if ( features != null && features.length > 0 ) {
-            final FeatureProviderDescription info = new FeatureProviderDescription(provider, props);
-            synchronized ( this.providers ) {
-                boolean changed = false;
-                for(final String n : features) {
-                    if ( n != null ) {
-                        final String name = n.trim();
-                        if ( name.length() > 0 ) {
-                            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();
-                }
-            }
-        }
-    }
-
-    /**
-     * Unbind a feature provider
-     */
-    protected void unbindFeatureProvider(final FeatureProvider provider, final Map<String, Object> props) {
-        final String[] features = provider.getFeatureNames();
-        if ( features != null && features.length > 0 ) {
-            final FeatureProviderDescription info = new FeatureProviderDescription(provider, props);
-            synchronized ( this.providers ) {
-                boolean changed = false;
-                for(final String n : features) {
-                    if ( n != null ) {
-                        final String name = n.trim();
-                        if ( name.length() > 0 ) {
-                            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();
-                }
-            }
-        }
-    }
-
-    private void calculateActiveProviders() {
-        final Map<String, FeatureProviderDescription> activeMap = new HashMap<String, FeatureImpl.FeatureProviderDescription>();
-        for(final Map.Entry<String, List<FeatureProviderDescription>> entry : this.providers.entrySet()) {
-            activeMap.put(entry.getKey(), entry.getValue().get(0));
-        }
-        this.activeProviders = activeMap;
-    }
+    @Reference
+    private FeatureManager manager;
 
     @Override
     public boolean isEnabled(final String featureName, final ExecutionContext context) {
-        boolean result = false;
-        final FeatureProviderDescription desc = this.activeProviders.get(featureName);
-        if ( desc != null ) {
-            final FeatureProvider prod = desc.getProvider();
-            result = prod.isEnabled(featureName, context);
-        }
-        return result;
+        return this.manager.isEnabled(featureName, context);
     }
 
     @Override
     public String[] getFeatureNames() {
-        return this.activeProviders.keySet().toArray(new String[this.activeProviders.size()]);
+        return this.manager.getFeatureNames();
     }
 
     @Override
     public boolean isAvailable(final String featureName) {
-        return this.activeProviders.containsKey(featureName);
-    }
-
-
-    /**
-     * Internal class caching some provider infos like service id and ranking.
-     */
-    private final static class FeatureProviderDescription implements Comparable<FeatureProviderDescription> {
-
-        public FeatureProvider provider;
-        public final int ranking;
-        public final long serviceId;
-
-        public FeatureProviderDescription(final FeatureProvider provider, final Map<String, Object> props) {
-            this.provider = provider;
-            final Object sr = props.get(Constants.SERVICE_RANKING);
-            if ( sr == null || !(sr instanceof Integer)) {
-                this.ranking = 0;
-            } else {
-                this.ranking = (Integer)sr;
-            }
-            this.serviceId = (Long)props.get(Constants.SERVICE_ID);
-        }
-
-        @Override
-        public int compareTo(final FeatureProviderDescription o) {
-            if ( this.ranking < o.ranking ) {
-                return 1;
-            } else if (this.ranking > o.ranking ) {
-                return -1;
-            }
-            // If ranks are equal, then sort by service id in descending order.
-            return (this.serviceId < o.serviceId) ? -1 : 1;
-        }
-
-        @Override
-        public boolean equals(final Object obj) {
-            if ( obj instanceof FeatureProviderDescription ) {
-                return ((FeatureProviderDescription)obj).serviceId == this.serviceId;
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + (int) (serviceId ^ (serviceId >>> 32));
-            return result;
-        }
-
-        public FeatureProvider getProvider() {
-            return provider;
-        }
+        // TODO Auto-generated method stub
+        return this.manager.isAvailable(featureName);
     }
 }
diff --git a/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureImpl.java b/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureManager.java
similarity index 85%
copy from src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureImpl.java
copy to src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureManager.java
index 65abe86..dad36fe 100644
--- a/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureImpl.java
+++ b/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureManager.java
@@ -28,7 +28,7 @@ import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.ReferencePolicy;
-import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.resource.Resource;
 import org.apache.sling.extensions.featureflags.ExecutionContext;
 import org.apache.sling.extensions.featureflags.Feature;
 import org.apache.sling.extensions.featureflags.FeatureProvider;
@@ -39,12 +39,11 @@ import org.osgi.framework.Constants;
  * It keeps track of all {@link FeatureProvider} services.
  */
 @Component
-@Service(value=Feature.class)
 @Reference(name="featureProvider",
            cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE,
            policy=ReferencePolicy.DYNAMIC,
            referenceInterface=FeatureProvider.class)
-public class FeatureImpl implements Feature {
+public class FeatureManager implements Feature {
 
     private final Map<String, List<FeatureProviderDescription>> providers = new HashMap<String, List<FeatureProviderDescription>>();
 
@@ -113,7 +112,7 @@ public class FeatureImpl implements Feature {
     }
 
     private void calculateActiveProviders() {
-        final Map<String, FeatureProviderDescription> activeMap = new HashMap<String, FeatureImpl.FeatureProviderDescription>();
+        final Map<String, FeatureProviderDescription> activeMap = new HashMap<String, FeatureManager.FeatureProviderDescription>();
         for(final Map.Entry<String, List<FeatureProviderDescription>> entry : this.providers.entrySet()) {
             activeMap.put(entry.getKey(), entry.getValue().get(0));
         }
@@ -141,6 +140,19 @@ public class FeatureImpl implements Feature {
         return this.activeProviders.containsKey(featureName);
     }
 
+    /**
+     * Checks whether a resource should be hidden for a feature.
+     * This check is only executed if {@link #isEnabled(String, ExecutionContext)}
+     * return true for the given feature/context.
+     */
+    public boolean hideResource(final String featureName, final Resource resource) {
+        final FeatureProviderDescription desc = this.activeProviders.get(featureName);
+        if ( desc != null ) {
+            final FeatureProvider prod = desc.getProvider();
+            return prod.hideResource(featureName, resource);
+        }
+        return false;
+    }
 
     /**
      * Internal class caching some provider infos like service id and ranking.
@@ -193,4 +205,16 @@ public class FeatureImpl implements Feature {
             return provider;
         }
     }
+
+    public String getResourceType(final String featureName, final String resourceType) {
+        final FeatureProviderDescription desc = this.activeProviders.get(featureName);
+        if ( desc != null ) {
+            final FeatureProvider prod = desc.getProvider();
+            final Map<String, String> mapping = prod.getResourceTypeMapping(featureName);
+            if ( mapping != null ) {
+                return mapping.get(resourceType);
+            }
+        }
+        return null;
+    }
 }
diff --git a/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceAccessImpl.java b/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceAccessImpl.java
index a3bed50..5840a3a 100644
--- a/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceAccessImpl.java
+++ b/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceAccessImpl.java
@@ -22,7 +22,6 @@ import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.Service;
 import org.apache.sling.api.resource.Resource;
-import org.apache.sling.extensions.featureflags.Feature;
 import org.apache.sling.resourceaccesssecurity.AllowingResourceAccessGate;
 import org.apache.sling.resourceaccesssecurity.ResourceAccessGate;
 
@@ -33,7 +32,7 @@ public class ResourceAccessImpl
     implements ResourceAccessGate {
 
     @Reference
-    private Feature feature;
+    private FeatureManager manager;
 
     @Override
     public GateResult canRead(final Resource resource) {
@@ -42,8 +41,10 @@ public class ResourceAccessImpl
         if ( info != null ) {
             for(final String name : info.enabledFeatures) {
                 // we can't check as Feature does not have the api (TODO - we deny for now)
-                available = false;
-                break;
+                available = !manager.hideResource(name, resource);
+                if ( !available) {
+                    break;
+                }
             }
         }
         return (available ? GateResult.DONTCARE : GateResult.DENIED);
diff --git a/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceAccessImpl.java b/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceDecoratorImpl.java
similarity index 53%
copy from src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceAccessImpl.java
copy to src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceDecoratorImpl.java
index a3bed50..5d2cbad 100644
--- a/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceAccessImpl.java
+++ b/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceDecoratorImpl.java
@@ -18,34 +18,51 @@
  */
 package org.apache.sling.extensions.featureflags.impl;
 
+import javax.servlet.http.HttpServletRequest;
+
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.Service;
 import org.apache.sling.api.resource.Resource;
-import org.apache.sling.extensions.featureflags.Feature;
-import org.apache.sling.resourceaccesssecurity.AllowingResourceAccessGate;
-import org.apache.sling.resourceaccesssecurity.ResourceAccessGate;
+import org.apache.sling.api.resource.ResourceDecorator;
+import org.apache.sling.api.resource.ResourceWrapper;
 
 @Component
-@Service(value=ResourceAccessGate.class)
-public class ResourceAccessImpl
-    extends AllowingResourceAccessGate
-    implements ResourceAccessGate {
+@Service(value=ResourceDecorator.class)
+public class ResourceDecoratorImpl implements ResourceDecorator {
 
     @Reference
-    private Feature feature;
+    private FeatureManager manager;
 
     @Override
-    public GateResult canRead(final Resource resource) {
-        boolean available = true;
+    public Resource decorate(final Resource resource) {
         final ExecutionContextFilter.ExecutionContextInfo info = ExecutionContextFilter.getCurrentExecutionContextInfo();
         if ( info != null ) {
             for(final String name : info.enabledFeatures) {
-                // we can't check as Feature does not have the api (TODO - we deny for now)
-                available = false;
-                break;
+
+                final String resourceType = resource.getResourceType();
+                final String overwriteType = manager.getResourceType(name, resourceType);
+                if ( overwriteType != null ) {
+                    return new ResourceWrapper(resource) {
+
+                        @Override
+                        public String getResourceType() {
+                            return overwriteType;
+                        }
+
+                        @Override
+                        public String getResourceSuperType() {
+                            return resourceType;
+                        }
+                    };
+                }
             }
         }
-        return (available ? GateResult.DONTCARE : GateResult.DENIED);
+        return resource;
+    }
+
+    @Override
+    public Resource decorate(final Resource resource, final HttpServletRequest request) {
+        return this.decorate(resource);
     }
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.