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>.