Author: cziegeler
Date: Thu Dec 19 03:46:14 2013
New Revision: 1552222
URL: http://svn.apache.org/r1552222
Log:
Implemet hiding of resource and decorating
Added:
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureManager.java
(with props)
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceDecoratorImpl.java
(with props)
Modified:
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/ExecutionContextFilter.java
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureImpl.java
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceAccessImpl.java
Modified:
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/ExecutionContextFilter.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/ExecutionContextFilter.java?rev=1552222&r1=1552221&r2=1552222&view=diff
==============================================================================
---
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/ExecutionContextFilter.java
(original)
+++
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/ExecutionContextFilter.java
Thu Dec 19 03:46:14 2013
@@ -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 impl
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 impl
enabledFeatures.add(name);
}
}
+ Collections.sort(enabledFeatures);
}
}
}
Modified:
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureImpl.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureImpl.java?rev=1552222&r1=1552221&r2=1552222&view=diff
==============================================================================
---
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureImpl.java
(original)
+++
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureImpl.java
Thu Dec 19 03:46:14 2013
@@ -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);
}
}
Added:
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureManager.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureManager.java?rev=1552222&view=auto
==============================================================================
---
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureManager.java
(added)
+++
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureManager.java
Thu Dec 19 03:46:14 2013
@@ -0,0 +1,220 @@
+/*
+ * 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.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.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;
+import org.osgi.framework.Constants;
+
+/**
+ * This service implements the feature handling.
+ * It keeps track of all {@link FeatureProvider} services.
+ */
+@Component
+@Reference(name="featureProvider",
+ cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE,
+ policy=ReferencePolicy.DYNAMIC,
+ referenceInterface=FeatureProvider.class)
+public class FeatureManager 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, FeatureManager.FeatureProviderDescription>();
+ for(final Map.Entry<String, List<FeatureProviderDescription>> entry :
this.providers.entrySet()) {
+ activeMap.put(entry.getKey(), entry.getValue().get(0));
+ }
+ this.activeProviders = activeMap;
+ }
+
+ @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;
+ }
+
+ @Override
+ public String[] getFeatureNames() {
+ return this.activeProviders.keySet().toArray(new
String[this.activeProviders.size()]);
+ }
+
+ @Override
+ public boolean isAvailable(final String featureName) {
+ 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.
+ */
+ 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;
+ }
+ }
+
+ 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;
+ }
+}
Propchange:
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureManager.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange:
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/FeatureManager.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified:
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceAccessImpl.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceAccessImpl.java?rev=1552222&r1=1552221&r2=1552222&view=diff
==============================================================================
---
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceAccessImpl.java
(original)
+++
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceAccessImpl.java
Thu Dec 19 03:46:14 2013
@@ -22,7 +22,6 @@ import org.apache.felix.scr.annotations.
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);
Added:
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceDecoratorImpl.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceDecoratorImpl.java?rev=1552222&view=auto
==============================================================================
---
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceDecoratorImpl.java
(added)
+++
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceDecoratorImpl.java
Thu Dec 19 03:46:14 2013
@@ -0,0 +1,68 @@
+/*
+ * 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.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.api.resource.ResourceDecorator;
+import org.apache.sling.api.resource.ResourceWrapper;
+
+@Component
+@Service(value=ResourceDecorator.class)
+public class ResourceDecoratorImpl implements ResourceDecorator {
+
+ @Reference
+ private FeatureManager manager;
+
+ @Override
+ public Resource decorate(final Resource resource) {
+ final ExecutionContextFilter.ExecutionContextInfo info =
ExecutionContextFilter.getCurrentExecutionContextInfo();
+ if ( info != null ) {
+ for(final String name : info.enabledFeatures) {
+
+ 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 resource;
+ }
+
+ @Override
+ public Resource decorate(final Resource resource, final HttpServletRequest
request) {
+ return this.decorate(resource);
+ }
+}
Propchange:
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceDecoratorImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceDecoratorImpl.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange:
sling/whiteboard/feature-flags/src/main/java/org/apache/sling/extensions/featureflags/impl/ResourceDecoratorImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain