You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by kw...@apache.org on 2016/11/24 14:30:41 UTC

svn commit: r1771152 - in /sling/trunk/contrib/extensions/security/src: main/java/org/apache/sling/security/impl/ test/java/org/apache/sling/security/impl/

Author: kwin
Date: Thu Nov 24 14:30:41 2016
New Revision: 1771152

URL: http://svn.apache.org/viewvc?rev=1771152&view=rev
Log:
SLING-6316 clarify description of OSGi configuration of the ContentDispositionFilter

change from Felix DS to OSGi annotations

Added:
    sling/trunk/contrib/extensions/security/src/main/java/org/apache/sling/security/impl/ContentDispositionFilterConfiguration.java   (with props)
Modified:
    sling/trunk/contrib/extensions/security/src/main/java/org/apache/sling/security/impl/ContentDispositionFilter.java
    sling/trunk/contrib/extensions/security/src/test/java/org/apache/sling/security/impl/ContentDispositionFilterTest.java

Modified: sling/trunk/contrib/extensions/security/src/main/java/org/apache/sling/security/impl/ContentDispositionFilter.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/security/src/main/java/org/apache/sling/security/impl/ContentDispositionFilter.java?rev=1771152&r1=1771151&r2=1771152&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/security/src/main/java/org/apache/sling/security/impl/ContentDispositionFilter.java (original)
+++ sling/trunk/contrib/extensions/security/src/main/java/org/apache/sling/security/impl/ContentDispositionFilter.java Thu Nov 24 14:30:41 2016
@@ -33,53 +33,24 @@ import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Properties;
-import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.PropertyUnbounded;
-import org.apache.felix.scr.annotations.Service;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.api.wrappers.SlingHttpServletResponseWrapper;
-import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.metatype.annotations.Designate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-@Component(metatype = true,
-description = "Request filter adding Content Disposition attachment for certain paths/content types",
-label=" Apache Sling Content Disposition Filter")
-@Service(value = Filter.class)
-@Properties({
-        @Property(name = "sling.filter.scope", value = { "request" }, propertyPrivate = true),
-        @Property(name = "service.ranking", intValue = -25000, propertyPrivate = true) })
+@Component(property={"sling.filter.scope=request", "service.ranking:Integer=25000"})
+@Designate(ocd=ContentDispositionFilterConfiguration.class)
 public class ContentDispositionFilter implements Filter {
 
     /** Logger. */
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
 
-    @Property(label = "Content Disposition Paths",
-            description = "These paths are checked by the filter. "+
-                    "Each entry is of the form 'path [ \":\" CSV of excluded content types ]'. " +
-                    "Invalid entries are logged and ignored."
-                    , unbounded = PropertyUnbounded.ARRAY, value = { "" })
-    private static final String PROP_CONTENT_DISPOSTION_PATHS = "sling.content.disposition.paths";
-
-    @Property(label = "Content Disposition Excluded Paths",
-            description = "These paths are excluded by the filter. "+
-                    "Each entry is of the form 'path'. "
-                    , unbounded = PropertyUnbounded.ARRAY, value = { "" })
-    private static final String PROP_CONTENT_DISPOSTION_EXCLUDED_PATHS = "sling.content.disposition.excluded.paths";
-
-    private static final boolean DEFAULT_ENABLE_CONTENT_DISPOSTION_ALL_PATHS = false;
-    @Property(boolValue = DEFAULT_ENABLE_CONTENT_DISPOSTION_ALL_PATHS ,
-              label = "Enable Content Disposition for all paths",
-              description ="This flag controls whether to enable" +
-                      " Content Disposition for all paths, except for the excluded paths defined by sling.content.disposition.excluded.paths")
-    private static final String PROP_ENABLE_CONTENT_DISPOSTION_ALL_PATHS = "sling.content.disposition.all.paths";
-
     /**
      * Set of paths
      */
@@ -97,14 +68,14 @@ public class ContentDispositionFilter im
     private boolean enableContentDispositionAllPaths;
 
     @Activate
-    private void activate(final Map<String, Object> props) {
-        String[] contentDispostionProps = PropertiesUtil.toStringArray(props.get(PROP_CONTENT_DISPOSTION_PATHS));
+    private void activate(ContentDispositionFilterConfiguration configuration) {
+        String[] contentDispositionPathsConfiguredValue = configuration.sling_content_disposition_paths();
 
         Set<String> paths = new HashSet<String>();
         List<String> pfxs = new ArrayList<String>();
         Map<String, Set<String>> contentTypesMap = new HashMap<String, Set<String>>();
 
-        for (String path : contentDispostionProps) {
+        for (String path : contentDispositionPathsConfiguredValue) {
             path = path.trim();
             if (path.length() > 0) {
                 int idx = path.indexOf('*');
@@ -112,7 +83,7 @@ public class ContentDispositionFilter im
 
                 if (colonIdx > -1 && colonIdx < idx) {
                     // ':'  in paths is not allowed
-                    logger.info("':' in paths is not allowed.");
+                    logger.info("wildcard ('*') in content type is not allowed, but found content type with value '{}'", path.substring(colonIdx));
                 } else {
                     String p = null;
                     if (idx >= 0) {
@@ -145,10 +116,10 @@ public class ContentDispositionFilter im
         contentDispositionPathsPfx = pfxs.toArray(new String[pfxs.size()]);
         contentTypesMapping = contentTypesMap.isEmpty()?Collections.<String, Set<String>>emptyMap(): contentTypesMap;
 
-        enableContentDispositionAllPaths =  PropertiesUtil.toBoolean(props.get(PROP_ENABLE_CONTENT_DISPOSTION_ALL_PATHS),DEFAULT_ENABLE_CONTENT_DISPOSTION_ALL_PATHS);
+        enableContentDispositionAllPaths =  configuration.sling_content_disposition_all_paths();
 
 
-        String[] contentDispostionExcludedPathsArray = PropertiesUtil.toStringArray(props.get(PROP_CONTENT_DISPOSTION_EXCLUDED_PATHS));
+        String[] contentDispostionExcludedPathsArray = configuration.sling_content_disposition_excluded_paths();
 
         contentDispositionExcludedPaths = new HashSet<String>(Arrays.asList(contentDispostionExcludedPathsArray));
 

Added: sling/trunk/contrib/extensions/security/src/main/java/org/apache/sling/security/impl/ContentDispositionFilterConfiguration.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/security/src/main/java/org/apache/sling/security/impl/ContentDispositionFilterConfiguration.java?rev=1771152&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/security/src/main/java/org/apache/sling/security/impl/ContentDispositionFilterConfiguration.java (added)
+++ sling/trunk/contrib/extensions/security/src/main/java/org/apache/sling/security/impl/ContentDispositionFilterConfiguration.java Thu Nov 24 14:30:41 2016
@@ -0,0 +1,38 @@
+/*
+ * 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.security.impl;
+
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+
+@ObjectClassDefinition(name="Apache Sling Content Disposition Filter", description="Request filter adding Content Disposition header with value 'attachment' for certain paths/content types. Independent of the configuration only resource paths are covered which contain a property named 'jcr:data' or 'jcr:content\\jcr:data'.")
+public @interface ContentDispositionFilterConfiguration {
+
+    @AttributeDefinition(name="Included Resource Paths & Content Types", description="These resource paths are covered by the filter. "+
+            "Each entry is of the form '<path> [ : <excluded content type> {,<excluded content type>} ]'. " +
+            "Invalid entries are logged and ignored. <path> must be an absolute path and may contain a wildcard ('*') at the end, to match every resource path with the given path prefix.")
+    String[] sling_content_disposition_paths() default {};
+
+    @AttributeDefinition(name="Excluded Resource Paths", description="These resource paths are excluded from the filter. "+
+                    "Each resource path must be given as absolute and fully qualified path. Prefix matching/wildcards are not supported.")
+    String[] sling_content_disposition_excluded_paths() default {};
+
+    @AttributeDefinition(name="Enable For All Resource Paths", description="This flag controls whether to enable" +
+            " this filter for all paths, except for the excluded paths defined by sling.content.disposition.excluded.paths. Setting this to 'true' leads to ignoring 'sling.content.disposition.path'.")
+    boolean sling_content_disposition_all_paths() default false;
+
+}

Propchange: sling/trunk/contrib/extensions/security/src/main/java/org/apache/sling/security/impl/ContentDispositionFilterConfiguration.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sling/trunk/contrib/extensions/security/src/test/java/org/apache/sling/security/impl/ContentDispositionFilterTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/security/src/test/java/org/apache/sling/security/impl/ContentDispositionFilterTest.java?rev=1771152&r1=1771151&r2=1771152&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/security/src/test/java/org/apache/sling/security/impl/ContentDispositionFilterTest.java (original)
+++ sling/trunk/contrib/extensions/security/src/test/java/org/apache/sling/security/impl/ContentDispositionFilterTest.java Thu Nov 24 14:30:41 2016
@@ -16,7 +16,7 @@
  */
 package org.apache.sling.security.impl;
 
-import java.util.HashMap;
+import java.lang.annotation.Annotation;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -30,6 +30,7 @@ import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.jmock.integration.junit4.JUnit4Mockery;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 
 import junitx.util.PrivateAccessor;
@@ -43,15 +44,67 @@ public class ContentDispositionFilterTes
 
     private static final String JCR_CONTENT_LEAF = "jcr:content";
 
+    @Before
+    public void setUp() {
+        contentDispositionFilter = new ContentDispositionFilter();
+    }
+    
+    /**
+     * Implementation of the annotation class used for the configuration of the ContentDispositionFilter.
+     * Unfortunately there is no way to hide the compiler warning: http://stackoverflow.com/a/13261789/5155923
+     */
+    private static final class Configuration implements ContentDispositionFilterConfiguration {
+
+        public Configuration(String[] paths, String[] excludedPaths, boolean enableForAllPaths) {
+            super();
+            this.paths = paths;
+            this.excludedPaths = excludedPaths;
+            this.enableForAllPaths = enableForAllPaths;
+        }
+
+        private final String paths[];
+        private final String excludedPaths[];
+        private final boolean enableForAllPaths;
+        
+        @Override
+        public Class<? extends Annotation> annotationType() {
+            return ContentDispositionFilterConfiguration.class;
+        }
+        
+        @Override
+        public String[] sling_content_disposition_paths() {
+            return paths;
+        }
+        
+        @Override
+        public String[] sling_content_disposition_excluded_paths() {
+            return excludedPaths;
+        }
+        
+        @Override
+        public boolean sling_content_disposition_all_paths() {
+            return enableForAllPaths;
+        }
+    }
+
+    private void callActivateWithConfiguration(String[] paths) throws Throwable {
+        callActivateWithConfiguration(paths, new String[]{});
+    }
+
+    private void callActivateWithConfiguration(String[] paths, String[] excludedPaths) throws Throwable {
+        callActivateWithConfiguration(paths, excludedPaths, false);
+    }
+    
+
+    private void callActivateWithConfiguration(String[] paths, String[] excludedPaths, boolean enableForAllPaths) throws Throwable {
+        ContentDispositionFilterConfiguration configuration = new Configuration(paths, excludedPaths, enableForAllPaths);
+        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{ContentDispositionFilterConfiguration.class},new Object[]{configuration});
+    }
+
     @SuppressWarnings("unchecked")
     @Test
     public void test_activator1() throws Throwable{
-        contentDispositionFilter = new ContentDispositionFilter();
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
+        callActivateWithConfiguration(new String[]{"/content/usergenerated"}, new String []{""});
         Set<String> contentDispositionPaths = ( Set<String> ) PrivateAccessor.getField(contentDispositionFilter, "contentDispositionPaths");
         Assert.assertEquals(1, contentDispositionPaths.size());
         String[] contentDispositionPathsPfx = ( String[] ) PrivateAccessor.getField(contentDispositionFilter, "contentDispositionPathsPfx");
@@ -63,13 +116,7 @@ public class ContentDispositionFilterTes
     @SuppressWarnings("unchecked")
     @Test
     public void test_activator2() throws Throwable{
-        contentDispositionFilter = new ContentDispositionFilter();
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated/*"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
-
+        callActivateWithConfiguration(new String[]{"/content/usergenerated/*"}, new String []{""});
         Set<String> contentDispositionPaths = ( Set<String> ) PrivateAccessor.getField(contentDispositionFilter, "contentDispositionPaths");
         Assert.assertEquals(0, contentDispositionPaths.size());
         String[] contentDispositionPathsPfx = ( String[] ) PrivateAccessor.getField(contentDispositionFilter, "contentDispositionPathsPfx");
@@ -81,13 +128,7 @@ public class ContentDispositionFilterTes
     @SuppressWarnings("unchecked")
     @Test
     public void test_activator3() throws Throwable{
-        contentDispositionFilter = new ContentDispositionFilter();
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/libs", "/content/usergenerated/*"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
-
+        callActivateWithConfiguration(new String[]{"/libs", "/content/usergenerated/*"}, new String[]{""});
         Set<String> contentDispositionPaths = ( Set<String> ) PrivateAccessor.getField(contentDispositionFilter, "contentDispositionPaths");
         Assert.assertEquals(1, contentDispositionPaths.size());
         String[] contentDispositionPathsPfx = ( String[] ) PrivateAccessor.getField(contentDispositionFilter, "contentDispositionPathsPfx");
@@ -99,13 +140,7 @@ public class ContentDispositionFilterTes
     @SuppressWarnings("unchecked")
     @Test
     public void test_activator5() throws Throwable{
-        contentDispositionFilter = new ContentDispositionFilter();
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"*"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
-
+        callActivateWithConfiguration(new String[]{"*"}, new String[]{""});
         Set<String> contentDispositionPaths = ( Set<String> ) PrivateAccessor.getField(contentDispositionFilter, "contentDispositionPaths");
         Assert.assertEquals(0, contentDispositionPaths.size());
         String[] contentDispositionPathsPfx = ( String[] ) PrivateAccessor.getField(contentDispositionFilter, "contentDispositionPathsPfx");
@@ -117,13 +152,7 @@ public class ContentDispositionFilterTes
     @SuppressWarnings("unchecked")
     @Test
     public void test_activator6() throws Throwable{
-        contentDispositionFilter = new ContentDispositionFilter();
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/libs:*"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
-
+        callActivateWithConfiguration(new String[]{"/libs:*"}, new String[]{""});
         Set<String> contentDispositionPaths = ( Set<String> ) PrivateAccessor.getField(contentDispositionFilter, "contentDispositionPaths");
         Assert.assertEquals(0, contentDispositionPaths.size());
         String[] contentDispositionPathsPfx = ( String[] ) PrivateAccessor.getField(contentDispositionFilter, "contentDispositionPathsPfx");
@@ -135,13 +164,7 @@ public class ContentDispositionFilterTes
     @SuppressWarnings("unchecked")
     @Test
     public void test_activator7() throws Throwable{
-        contentDispositionFilter = new ContentDispositionFilter();
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/libs:text/html,text/plain","/content/usergenerated/*:image/jpeg"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
-
+        callActivateWithConfiguration(new String[]{"/libs:text/html,text/plain","/content/usergenerated/*:image/jpeg"}, new String[]{""});
         Set<String> contentDispositionPaths = ( Set<String> ) PrivateAccessor.getField(contentDispositionFilter, "contentDispositionPaths");
         Assert.assertEquals(1, contentDispositionPaths.size());
         String[] contentDispositionPathsPfx = ( String[] ) PrivateAccessor.getField(contentDispositionFilter, "contentDispositionPathsPfx");
@@ -158,29 +181,19 @@ public class ContentDispositionFilterTes
         userGeneratedMapping.contains("image/jpeg");
      }
 
-    @SuppressWarnings("unchecked")
+	@SuppressWarnings("unchecked")
     @Test
     public void test_activator8() throws Throwable{
-        contentDispositionFilter = new ContentDispositionFilter();
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/libs:text/html,text/plain","/content/usergenerated/*:image/jpeg"});
-        props.put("sling.content.disposition.excluded.paths", new String []{});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
-
+        callActivateWithConfiguration(new String[]{"/libs:text/html,text/plain","/content/usergenerated/*:image/jpeg"}, new String[]{});
+        
         Set<String> contentDispositionExcludedPaths = ( Set<String> ) PrivateAccessor.getField(contentDispositionFilter, "contentDispositionExcludedPaths");
         Assert.assertEquals(0, contentDispositionExcludedPaths.size());
-     }
-
+    }
+     
     @SuppressWarnings("unchecked")
     @Test
     public void test_activator9() throws Throwable{
-        contentDispositionFilter = new ContentDispositionFilter();
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/libs:text/html,text/plain","/content/usergenerated/*:image/jpeg"});
-        props.put("sling.content.disposition.excluded.paths", new String []{"/content", "/libs"});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
+        callActivateWithConfiguration(new String[]{"/libs:text/html,text/plain","/content/usergenerated/*:image/jpeg"}, new String[]{"/content", "/libs"});
 
         Set<String> contentDispositionExcludedPaths = ( Set<String> ) PrivateAccessor.getField(contentDispositionFilter, "contentDispositionExcludedPaths");
         Assert.assertEquals(2, contentDispositionExcludedPaths.size());
@@ -210,15 +223,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletRequest request = context.mock(SlingHttpServletRequest.class);
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
-
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
-
+        callActivateWithConfiguration(new String[]{"/content/usergenerated"}, new String[]{""});
 
         context.checking(new Expectations() {
             {
@@ -247,14 +252,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletRequest request = context.mock(SlingHttpServletRequest.class);
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
-
+        callActivateWithConfiguration(new String[]{"/content/usergenerated"}, new String[]{""});
 
         context.checking(new Expectations() {
             {
@@ -283,14 +281,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
         final ValueMap properties = context.mock(ValueMap.class);
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
-
+		callActivateWithConfiguration(new String[]{"/content/usergenerated"}, new String[]{""});
 
         final AtomicInteger counter =  new AtomicInteger();
 
@@ -331,14 +322,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletRequest request = context.mock(SlingHttpServletRequest.class);
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated/*"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
-
+        callActivateWithConfiguration(new String[]{"/content/usergenerated/*"}, new String[]{""});
 
         context.checking(new Expectations() {
             {
@@ -367,13 +351,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
         final ValueMap properties = context.mock(ValueMap.class);
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated/*"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
+        callActivateWithConfiguration(new String[]{"/content/usergenerated/*"}, new String[]{""});
 
         final AtomicInteger counter =  new AtomicInteger();
 
@@ -415,13 +393,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
         final ValueMap properties = context.mock(ValueMap.class);
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated/*"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
+        callActivateWithConfiguration(new String[]{"/content/usergenerated/*"}, new String[]{""});
 
         final AtomicInteger counter =  new AtomicInteger();
 
@@ -462,14 +434,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletRequest request = context.mock(SlingHttpServletRequest.class);
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated:text/html,text/plain"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
-
+        callActivateWithConfiguration(new String[]{"/content/usergenerated:text/html,text/plain"}, new String[]{""});
 
         context.checking(new Expectations() {
             {
@@ -498,14 +463,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletRequest request = context.mock(SlingHttpServletRequest.class);
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated:text/html,text/plain"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
-
+        callActivateWithConfiguration(new String[]{"/content/usergenerated:text/html,text/plain"}, new String[]{""});
 
         context.checking(new Expectations() {
             {
@@ -533,14 +491,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletRequest request = context.mock(SlingHttpServletRequest.class);
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated:text/html,text/plain"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
-
+        callActivateWithConfiguration(new String[]{"/content/usergenerated:text/html,text/plain"}, new String[]{""});
 
         context.checking(new Expectations() {
             {
@@ -570,12 +521,7 @@ public class ContentDispositionFilterTes
         final Resource resource = context.mock(Resource.class, "resource" );
         final ValueMap properties = context.mock(ValueMap.class);
         contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated:text/html,text/plain"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
+        callActivateWithConfiguration(new String[]{"/content/usergenerated:text/html,text/plain"}, new String[]{""});
 
         final AtomicInteger counter =  new AtomicInteger();
 
@@ -616,14 +562,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletRequest request = context.mock(SlingHttpServletRequest.class);
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated/*:text/html,text/plain"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
-
+        callActivateWithConfiguration(new String[]{"/content/usergenerated/*:text/html,text/plain"}, new String[]{""});
 
         context.checking(new Expectations() {
             {
@@ -652,14 +591,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletRequest request = context.mock(SlingHttpServletRequest.class);
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated/*:text/html,text/plain"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
-
+        callActivateWithConfiguration(new String[]{"/content/usergenerated/*:text/html,text/plain"}, new String[]{""});
 
         context.checking(new Expectations() {
             {
@@ -687,14 +619,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletRequest request = context.mock(SlingHttpServletRequest.class);
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated/*:text/html,text/plain"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
-
+        callActivateWithConfiguration(new String[]{"/content/usergenerated/*:text/html,text/plain"}, new String[]{""});
 
         context.checking(new Expectations() {
             {
@@ -723,13 +648,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
         final ValueMap properties = context.mock(ValueMap.class);
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated/*:text/html,text/plain"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
+        callActivateWithConfiguration(new String[]{"/content/usergenerated/*:text/html,text/plain"}, new String[]{""});
 
         final AtomicInteger counter =  new AtomicInteger();
 
@@ -775,13 +694,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
         final ValueMap properties = context.mock(ValueMap.class);
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
+        callActivateWithConfiguration(new String[]{"/content/usergenerated"}, new String[]{""});
 
         final AtomicInteger counter =  new AtomicInteger();
 
@@ -830,13 +743,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
         final ValueMap properties = context.mock(ValueMap.class);
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
+        callActivateWithConfiguration(new String[]{"/content/usergenerated"}, new String[]{""});
 
         final AtomicInteger counter =  new AtomicInteger();
 
@@ -887,13 +794,7 @@ public class ContentDispositionFilterTes
         final Resource resource = context.mock(Resource.class, "resource" );
         final ValueMap properties = context.mock(ValueMap.class);
         contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-        props.put("sling.content.disposition.all.paths", false);
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
+        callActivateWithConfiguration(new String[]{"/content/usergenerated"}, new String[]{""}, false);
 
         final AtomicInteger counter =  new AtomicInteger();
 
@@ -935,21 +836,13 @@ public class ContentDispositionFilterTes
         Assert.assertEquals(0, counter.intValue());
     }
 
-
     @Test
     public void test_doFilter18() throws Throwable{
         final SlingHttpServletRequest request = context.mock(SlingHttpServletRequest.class);
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
         final ValueMap properties = context.mock(ValueMap.class);
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated"});
-        props.put("sling.content.disposition.excluded.paths", new String []{""});
-        props.put("sling.content.disposition.all.paths", true);
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
+        callActivateWithConfiguration(new String[]{"/content/usergenerated"}, new String[]{""}, true);
 
         final AtomicInteger counter =  new AtomicInteger();
 
@@ -997,14 +890,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
         final ValueMap properties = context.mock(ValueMap.class);
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated"});
-        props.put("sling.content.disposition.excluded.paths", new String []{"/content"});
-        props.put("sling.content.disposition.all.paths", true);
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
+        callActivateWithConfiguration(new String[]{"/content/usergenerated"}, new String[]{"/content"}, true);
 
         final AtomicInteger counter =  new AtomicInteger();
 
@@ -1052,14 +938,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
         final ValueMap properties = context.mock(ValueMap.class);
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated"});
-        props.put("sling.content.disposition.excluded.paths", new String []{"/content/other"});
-        props.put("sling.content.disposition.all.paths", true);
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
+        callActivateWithConfiguration(new String[]{"/content/usergenerated"}, new String[]{"/content/other"}, true);
 
         final AtomicInteger counter =  new AtomicInteger();
 
@@ -1107,14 +986,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
         final ValueMap properties = context.mock(ValueMap.class);
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated"});
-        props.put("sling.content.disposition.excluded.paths", new String []{"/content"});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
-
+        callActivateWithConfiguration(new String[]{"/content/usergenerated"}, new String[]{"/content"});
 
         final AtomicInteger counter =  new AtomicInteger();
 
@@ -1156,13 +1028,7 @@ public class ContentDispositionFilterTes
         final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
         final Resource resource = context.mock(Resource.class, "resource" );
         final ValueMap properties = context.mock(ValueMap.class);
-        contentDispositionFilter = new ContentDispositionFilter();
-
-        final Map<String, Object> props = new HashMap<String, Object>();
-        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated"});
-        props.put("sling.content.disposition.excluded.paths", new String []{"/content/usergenerated"});
-
-        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{Map.class},new Object[]{props});
+        callActivateWithConfiguration(new String[]{"/content/usergenerated"}, new String[]{"/content/usergenerated"});
 
         final AtomicInteger counter =  new AtomicInteger();
         context.checking(new Expectations() {