You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by to...@apache.org on 2016/11/23 10:22:05 UTC

svn commit: r1770942 - in /sling/trunk/contrib/extensions/distribution: core/ core/src/main/java/org/apache/sling/distribution/packaging/impl/ core/src/main/java/org/apache/sling/distribution/serialization/ core/src/main/java/org/apache/sling/distribut...

Author: tommaso
Date: Wed Nov 23 10:22:05 2016
New Revision: 1770942

URL: http://svn.apache.org/viewvc?rev=1770942&view=rev
Log:
SLING-5815 - expose content serializer

Added:
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/DistributionExportFilter.java   (with props)
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/DistributionExportOptions.java   (with props)
    sling/trunk/contrib/extensions/distribution/core/src/test/java/org/apache/sling/distribution/serialization/DistributionExportFilterTest.java   (with props)
    sling/trunk/contrib/extensions/distribution/core/src/test/java/org/apache/sling/distribution/serialization/impl/vlt/FileVaultContentSerializerTest.java   (with props)
    sling/trunk/contrib/extensions/distribution/core/src/test/resources/vlt/
    sling/trunk/contrib/extensions/distribution/core/src/test/resources/vlt/dp.vlt   (with props)
Modified:
    sling/trunk/contrib/extensions/distribution/core/pom.xml
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/packaging/impl/AbstractDistributionPackageBuilder.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/packaging/impl/FileDistributionPackageBuilder.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/packaging/impl/ResourceDistributionPackageBuilder.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/DistributionContentSerializer.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/DistributionPackageBuilderFactory.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/FileVaultContentSerializer.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/VaultDistributionPackageBuilderFactory.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/VltUtils.java
    sling/trunk/contrib/extensions/distribution/core/src/test/java/org/apache/sling/distribution/queue/impl/PriorityQueueDispatchingStrategyTest.java
    sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/avro/AvroContentSerializer.java
    sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/avro/AvroDistributionContentSerializerFactory.java
    sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/kryo/KryoContentSerializer.java
    sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/kryo/KryoDistributionContentSerializerFactory.java
    sling/trunk/contrib/extensions/distribution/extensions/src/test/java/org/apache/sling/distribution/serialization/impl/avro/AvroContentSerializerTest.java
    sling/trunk/contrib/extensions/distribution/extensions/src/test/java/org/apache/sling/distribution/serialization/impl/kryo/KryoContentSerializerTest.java

Modified: sling/trunk/contrib/extensions/distribution/core/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/pom.xml?rev=1770942&r1=1770941&r2=1770942&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/pom.xml (original)
+++ sling/trunk/contrib/extensions/distribution/core/pom.xml Wed Nov 23 10:22:05 2016
@@ -68,7 +68,9 @@
                     <instructions>
                         <Bundle-SymbolicName>org.apache.sling.distribution.core</Bundle-SymbolicName>
                         <Export-Package>
-                            org.apache.sling.distribution.util
+                            org.apache.sling.distribution.util,
+                            org.apache.sling.distribution.common,
+                            org.apache.sling.distribution.serialization
                         </Export-Package>
                         <Import-Package>
                             org.apache.http.nio.*;resolution:=optional,
@@ -125,6 +127,12 @@
             <version>1.1.14</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.testing.resourceresolver-mock</artifactId>
+            <version>1.1.12</version>
+            <scope>test</scope>
+        </dependency>
         <!-- SLING -->
         <dependency>
             <groupId>org.apache.sling</groupId>
@@ -267,6 +275,12 @@
             <version>2.0.0</version>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.testing.resourceresolver-mock</artifactId>
+            <version>1.1.15-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
 
     </dependencies>
     <reporting>

Modified: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/packaging/impl/AbstractDistributionPackageBuilder.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/packaging/impl/AbstractDistributionPackageBuilder.java?rev=1770942&r1=1770941&r2=1770942&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/packaging/impl/AbstractDistributionPackageBuilder.java (original)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/packaging/impl/AbstractDistributionPackageBuilder.java Wed Nov 23 10:22:05 2016
@@ -26,9 +26,13 @@ import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.distribution.DistributionRequest;
 import org.apache.sling.distribution.DistributionRequestType;
@@ -65,7 +69,6 @@ public abstract class AbstractDistributi
 
         request = VltUtils.sanitizeRequest(request);
 
-
         if (DistributionRequestType.ADD.equals(request.getRequestType())) {
             distributionPackage = createPackageForAdd(resourceResolver, request);
         } else if (DistributionRequestType.DELETE.equals(request.getRequestType())) {
@@ -197,10 +200,8 @@ public abstract class AbstractDistributi
         } finally {
             IOUtils.closeQuietly(inputStream);
         }
-
     }
 
-
     @CheckForNull
     public DistributionPackage getPackage(@Nonnull ResourceResolver resourceResolver, @Nonnull String id) {
         DistributionPackage distributionPackage = SimpleDistributionPackage.fromIdString(id, type);
@@ -221,6 +222,7 @@ public abstract class AbstractDistributi
     protected Session getSession(ResourceResolver resourceResolver) throws RepositoryException {
         Session session = resourceResolver.adaptTo(Session.class);
         if (session != null) {
+            // this is needed in order to avoid loops in sync case when there're deletions, otherwise it could work with sling resources
             DistributionJcrUtils.setDoNotDistribute(session);
         } else {
             throw new RepositoryException("could not obtain a session from calling user " + resourceResolver.getUserID());
@@ -256,4 +258,62 @@ public abstract class AbstractDistributi
     @CheckForNull
     protected abstract DistributionPackage getPackageInternal(@Nonnull ResourceResolver resourceResolver, @Nonnull String id);
 
+    /**
+     * extract the set of paths of resources that should be included in the package
+     * @param request the request
+     * @param resourceResolver the resource resolver used to browse the resource tree
+     * @return a set of paths
+     */
+    protected Set<String> readPaths(DistributionRequest request, ResourceResolver resourceResolver) {
+        Set<String> paths = new HashSet<String>();
+
+        for (String path : request.getPaths()) {
+            paths.add(path);
+            Resource resource = resourceResolver.getResource(path);
+            if (request.isDeep(path)) {
+                addSubtree(paths, resource);
+            } else {
+                for (Resource child : resource.getChildren()) {
+                    addFilteredPaths(request, child, paths);
+                }
+            }
+        }
+        return paths;
+    }
+
+    private void addFilteredPaths(DistributionRequest request, Resource resource, Set<String> paths) {
+        String path = resource.getPath();
+        if (filtersAllow(request.getFilters(path), path)) {
+            paths.add(path);
+            for (Resource child : resource.getChildren()) {
+                addFilteredPaths(request, child, paths);
+            }
+        }
+    }
+
+    private boolean filtersAllow(String[] filters, String path) {
+        boolean allowed = false;
+        for (String pattern : filters) {
+            if (pattern.startsWith("+")) {
+                if (Pattern.compile(pattern.substring(1)).matcher(path).matches()) {
+                    allowed = true;
+                }
+            } else if (pattern.startsWith("-")) {
+                if (Pattern.compile(pattern.substring(1)).matcher(path).matches()) {
+                    allowed = false;
+                }
+            } else {
+                allowed = Pattern.compile(pattern).matcher(path).matches();
+            }
+        }
+        return allowed;
+    }
+
+    private void addSubtree(Set<String> paths, Resource resource) {
+        for (Resource r : resource.getChildren()) {
+            paths.add(r.getPath());
+            addSubtree(paths, r);
+        }
+    }
+
 }

Modified: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/packaging/impl/FileDistributionPackageBuilder.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/packaging/impl/FileDistributionPackageBuilder.java?rev=1770942&r1=1770941&r2=1770942&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/packaging/impl/FileDistributionPackageBuilder.java (original)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/packaging/impl/FileDistributionPackageBuilder.java Wed Nov 23 10:22:05 2016
@@ -19,9 +19,7 @@
 
 package org.apache.sling.distribution.packaging.impl;
 
-import static org.apache.sling.distribution.util.impl.DigestUtils.openDigestOutputStream;
-import static org.apache.sling.distribution.util.impl.DigestUtils.readDigestMessage;
-
+import javax.annotation.Nonnull;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -29,9 +27,9 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.security.DigestOutputStream;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
-
-import javax.annotation.Nonnull;
+import java.util.NavigableMap;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.sling.api.resource.ResourceResolver;
@@ -40,10 +38,15 @@ import org.apache.sling.distribution.com
 import org.apache.sling.distribution.packaging.DistributionPackage;
 import org.apache.sling.distribution.packaging.DistributionPackageBuilder;
 import org.apache.sling.distribution.serialization.DistributionContentSerializer;
+import org.apache.sling.distribution.serialization.DistributionExportFilter;
+import org.apache.sling.distribution.serialization.DistributionExportOptions;
 import org.apache.sling.distribution.serialization.impl.vlt.VltUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.sling.distribution.util.impl.DigestUtils.openDigestOutputStream;
+import static org.apache.sling.distribution.util.impl.DigestUtils.readDigestMessage;
+
 /**
  * A {@link DistributionPackageBuilder} based on files.
  */
@@ -53,19 +56,24 @@ public class FileDistributionPackageBuil
     private final File tempDirectory;
     private final String digestAlgorithm;
     private final DistributionContentSerializer distributionContentSerializer;
+    private final NavigableMap<String, List<String>> nodeFilters;
+    private final NavigableMap<String, List<String>> propertyFilters;
 
     public FileDistributionPackageBuilder(String type,
                                           DistributionContentSerializer distributionContentSerializer,
                                           String tempFilesFolder,
-                                          String digestAlgorithm) {
+                                          String digestAlgorithm, String[] nodeFilters,
+                                          String[] propertyFilters) {
         super(type);
         this.distributionContentSerializer = distributionContentSerializer;
+        this.nodeFilters = VltUtils.parseFilters(nodeFilters);
+        this.propertyFilters = VltUtils.parseFilters(propertyFilters);
         this.tempDirectory = VltUtils.getTempFolder(tempFilesFolder);
         this.digestAlgorithm = digestAlgorithm;
     }
 
     @Override
-    protected DistributionPackage createPackageForAdd(@Nonnull ResourceResolver resourceResolver, @Nonnull DistributionRequest request) throws DistributionException {
+    protected DistributionPackage createPackageForAdd(@Nonnull ResourceResolver resourceResolver, @Nonnull final DistributionRequest request) throws DistributionException {
         DistributionPackage distributionPackage;
         OutputStream outputStream = null;
         String digestMessage = null;
@@ -80,7 +88,9 @@ public class FileDistributionPackageBuil
                 outputStream = new FileOutputStream(file);
             }
 
-            distributionContentSerializer.exportToStream(resourceResolver, request, outputStream);
+            final DistributionExportFilter filter = distributionContentSerializer.isRequestFiltering() ? DistributionExportFilter.createFilter(request, nodeFilters, propertyFilters) : null;
+            DistributionExportOptions distributionExportOptions = new DistributionExportOptions(request, filter);
+            distributionContentSerializer.exportToStream(resourceResolver, distributionExportOptions, outputStream);
             outputStream.flush();
 
             if (digestAlgorithm != null) {
@@ -137,7 +147,6 @@ public class FileDistributionPackageBuil
             throws DistributionException {
         try {
             distributionContentSerializer.importFromStream(resourceResolver, inputStream);
-
             return true;
         } finally {
             IOUtils.closeQuietly(inputStream);

Modified: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/packaging/impl/ResourceDistributionPackageBuilder.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/packaging/impl/ResourceDistributionPackageBuilder.java?rev=1770942&r1=1770941&r2=1770942&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/packaging/impl/ResourceDistributionPackageBuilder.java (original)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/packaging/impl/ResourceDistributionPackageBuilder.java Wed Nov 23 10:22:05 2016
@@ -25,9 +25,12 @@ import static org.apache.sling.distribut
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.security.DigestOutputStream;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.NavigableMap;
 import java.util.UUID;
 
 import javax.annotation.Nonnull;
@@ -41,6 +44,8 @@ import org.apache.sling.distribution.Dis
 import org.apache.sling.distribution.common.DistributionException;
 import org.apache.sling.distribution.packaging.DistributionPackage;
 import org.apache.sling.distribution.serialization.DistributionContentSerializer;
+import org.apache.sling.distribution.serialization.DistributionExportFilter;
+import org.apache.sling.distribution.serialization.DistributionExportOptions;
 import org.apache.sling.distribution.serialization.impl.vlt.VltUtils;
 import org.apache.sling.distribution.util.impl.FileBackedMemoryOutputStream;
 import org.apache.sling.distribution.util.impl.FileBackedMemoryOutputStream.MemoryUnit;
@@ -59,6 +64,8 @@ public class ResourceDistributionPackage
     private final MemoryUnit memoryUnit;
     private final boolean useOffHeapMemory;
     private final String digestAlgorithm;
+    private final NavigableMap<String, List<String>> nodeFilters;
+    private final NavigableMap<String, List<String>> propertyFilters;
 
     public ResourceDistributionPackageBuilder(String type,
                                               DistributionContentSerializer distributionContentSerializer,
@@ -66,9 +73,12 @@ public class ResourceDistributionPackage
                                               int fileThreshold,
                                               MemoryUnit memoryUnit,
                                               boolean useOffHeapMemory,
-                                              String digestAlgorithm) {
+                                              String digestAlgorithm, String[] nodeFilters,
+                                              String[] propertyFilters) {
         super(type);
         this.distributionContentSerializer = distributionContentSerializer;
+        this.nodeFilters = VltUtils.parseFilters(nodeFilters);
+        this.propertyFilters = VltUtils.parseFilters(propertyFilters);
         this.packagesPath = PREFIX_PATH + type + "/data";
         this.tempDirectory = VltUtils.getTempFolder(tempFilesFolder);
         this.fileThreshold = fileThreshold;
@@ -90,9 +100,9 @@ public class ResourceDistributionPackage
                 outputStream = new FileBackedMemoryOutputStream(fileThreshold, memoryUnit, useOffHeapMemory, tempDirectory, "distrpck-create-", "." + getType());
                 if (digestAlgorithm != null) {
                     digestStream = openDigestOutputStream(outputStream, digestAlgorithm);
-                    distributionContentSerializer.exportToStream(resourceResolver, request, digestStream);
+                    export(resourceResolver, request, digestStream);
                 } else {
-                    distributionContentSerializer.exportToStream(resourceResolver, request, outputStream);
+                    export(resourceResolver, request, outputStream);
                 }
                 outputStream.flush();
 
@@ -125,6 +135,12 @@ public class ResourceDistributionPackage
         return distributionPackage;
     }
 
+    private void export(@Nonnull ResourceResolver resourceResolver, @Nonnull final DistributionRequest request, OutputStream outputStream) throws DistributionException {
+        final DistributionExportFilter filter = distributionContentSerializer.isRequestFiltering() ? DistributionExportFilter.createFilter(request, nodeFilters, propertyFilters) : null;
+        DistributionExportOptions distributionExportOptions = new DistributionExportOptions(request, filter);
+        distributionContentSerializer.exportToStream(resourceResolver, distributionExportOptions, outputStream);
+    }
+
     @Override
     protected DistributionPackage readPackageInternal(@Nonnull ResourceResolver resourceResolver, @Nonnull InputStream inputStream)
             throws DistributionException {

Modified: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/DistributionContentSerializer.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/DistributionContentSerializer.java?rev=1770942&r1=1770941&r2=1770942&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/DistributionContentSerializer.java (original)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/DistributionContentSerializer.java Wed Nov 23 10:22:05 2016
@@ -23,7 +23,6 @@ import java.io.OutputStream;
 
 import aQute.bnd.annotation.ConsumerType;
 import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.distribution.DistributionRequest;
 import org.apache.sling.distribution.common.DistributionException;
 
 /**
@@ -34,24 +33,32 @@ public interface DistributionContentSeri
 
     /**
      * extracts the resources identified by the given request into the given outputStream
-     * @param resourceResolver the user resource resolver
-     * @param request a distribution request
+     * @param resourceResolver the resource resolver used to access resources to export
+     * @param exportOptions export options
      * @param outputStream the output stream
      * @throws DistributionException if extraction fails for some reason
      */
-    void exportToStream(ResourceResolver resourceResolver, DistributionRequest request, OutputStream outputStream) throws DistributionException;
+    void exportToStream(ResourceResolver resourceResolver, DistributionExportOptions exportOptions,
+                        OutputStream outputStream) throws DistributionException;
 
     /**
      * imports the given stream
-     * @param resourceResolver the user resource resolver
-     * @param stream the stream to import
+     * @param resourceResolver the resource resolver used to write resources
+     * @param inputStream the stream to import
      * @throws DistributionException if importing fails for some reason
      */
-    void importFromStream(ResourceResolver resourceResolver, InputStream stream) throws DistributionException;
+    void importFromStream(ResourceResolver resourceResolver, InputStream inputStream) throws DistributionException;
 
     /**
      * retrieve the name of this content serializer
      * @return the name of this content serializer
      */
     String getName();
+
+    /**
+     * whether or not this {@link DistributionContentSerializer} can build package filters for including / excluding
+     * certain resources / attributes directly from a {@link org.apache.sling.distribution.DistributionRequest}
+     * @return {@code true} if it can build filters from a request, {@code false} otherwise
+     */
+    boolean isRequestFiltering();
 }

Added: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/DistributionExportFilter.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/DistributionExportFilter.java?rev=1770942&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/DistributionExportFilter.java (added)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/DistributionExportFilter.java Wed Nov 23 10:22:05 2016
@@ -0,0 +1,203 @@
+/*
+ * 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.distribution.serialization;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.NavigableMap;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.sling.distribution.DistributionRequest;
+
+/**
+ * A filter is responsible for storing information about which resources / attributes should be serialized.
+ */
+public class DistributionExportFilter {
+
+    private final Set<TreeFilter> nodeFilters = new HashSet<TreeFilter>();
+    private TreeFilter propertyFilter;
+
+    private DistributionExportFilter() {
+        // can only be constructed by #createFilter
+    }
+
+    public Set<TreeFilter> getNodeFilters() {
+        return nodeFilters;
+    }
+
+    public TreeFilter getPropertyFilter() {
+        return propertyFilter;
+    }
+
+    /**
+     * create a filter based on a request and global node and property filters
+     * @param distributionRequest the request
+     * @param nodeFilters the node level filters
+     * @param propertyFilters the property level filters
+     * @return a filter
+     */
+    public static DistributionExportFilter createFilter(DistributionRequest distributionRequest,
+                                                        NavigableMap<String, List<String>> nodeFilters,
+                                                        NavigableMap<String, List<String>> propertyFilters) {
+        DistributionExportFilter exportFilter = new DistributionExportFilter();
+
+        for (String path : distributionRequest.getPaths()) {
+
+            boolean deep = distributionRequest.isDeep(path);
+            TreeFilter treeFilter = new TreeFilter(path);
+
+            if (deep) {
+                treeFilter.addDeepInclude(path);
+            } else {
+                treeFilter.addInclude(path);
+            }
+
+            List<String> patterns = new LinkedList<String>();
+            patterns.addAll(Arrays.asList(distributionRequest.getFilters(path)));
+            initFilter(nodeFilters, treeFilter, patterns);
+
+            exportFilter.addNodeFilter(treeFilter);
+
+        }
+        // Set property path filters
+        TreeFilter propertyFilterSet = new TreeFilter("/");
+        initFilter(propertyFilters, propertyFilterSet, new ArrayList<String>());
+        exportFilter.setPropertyFilter(propertyFilterSet);
+
+        return exportFilter;
+    }
+
+    private void addNodeFilter(TreeFilter filter) {
+        nodeFilters.add(filter);
+    }
+
+    private static void initFilter(NavigableMap<String, List<String>> globalFilters, TreeFilter treeFilter, List<String> patterns) {
+        // add the most specific filter rules
+        for (String key : globalFilters.descendingKeySet()) {
+            if (treeFilter.getPath().startsWith(key)) {
+                patterns.addAll(globalFilters.get(key));
+                break;
+            }
+        }
+
+        for (String pattern : patterns) {
+            TreeFilter.Entry entry = extractPathPattern(pattern);
+
+            if (entry.isInclude()) {
+                treeFilter.addInclude(entry.getPath());
+            } else {
+                treeFilter.addExclude(entry.getPath());
+            }
+        }
+    }
+
+    private static TreeFilter.Entry extractPathPattern(String pattern) {
+        TreeFilter.Entry result;
+        if (pattern.startsWith("+")) {
+            result = new TreeFilter.Entry(pattern.substring(1), true);
+        } else if (pattern.startsWith("-")) {
+            result = new TreeFilter.Entry(pattern.substring(1), false);
+        } else {
+            result = new TreeFilter.Entry(pattern, true);
+        }
+
+        return result;
+    }
+
+    private void setPropertyFilter(TreeFilter propertyFilter) {
+        this.propertyFilter = propertyFilter;
+    }
+
+    /**
+     * a filter is responsible for finding the resources that should be serialized unders a certain path
+     */
+    public static class TreeFilter {
+        private final String path;
+        private final Collection<String> includes;
+        private final Collection<String> excludes;
+        private final Collection<String> deepIncludes;
+
+        public TreeFilter(String path) {
+            this.path = path;
+            this.includes = new TreeSet<String>();
+            this.deepIncludes = new TreeSet<String>();
+            this.excludes = new TreeSet<String>();
+        }
+
+        public void addInclude(String path) {
+            includes.add(path);
+        }
+
+        public void addDeepInclude(String path) {
+            deepIncludes.add(path);
+        }
+
+        public void addExclude(String path) {
+            excludes.add(path);
+        }
+
+        public String getPath() {
+            return path;
+        }
+
+        /**
+         * check whether a resource with a certain path should be included in the serialized output
+         * @param path a path
+         * @return {@code true} if the path mathces the filter, {@code false} otherwise
+         */
+        public boolean matches(String path) {
+            boolean match = (includes.isEmpty() && excludes.isEmpty()) || includes.contains(path);
+            if (!match) {
+                for (String di : deepIncludes) {
+                    match = path.startsWith(di);
+                    if (match) {
+                        break;
+                    }
+                }
+            }
+            match &= !excludes.contains(path);
+            return match;
+        }
+
+        private static class Entry {
+            private final String path;
+            private final boolean include;
+
+            public Entry(String path, boolean include) {
+                this.path = path;
+                this.include = include;
+            }
+
+            public boolean isInclude() {
+                return include;
+            }
+
+            public String getPath() {
+                return path;
+            }
+        }
+    }
+
+
+}

Propchange: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/DistributionExportFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/DistributionExportOptions.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/DistributionExportOptions.java?rev=1770942&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/DistributionExportOptions.java (added)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/DistributionExportOptions.java Wed Nov 23 10:22:05 2016
@@ -0,0 +1,55 @@
+/*
+ * 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.distribution.serialization;
+
+import java.io.OutputStream;
+
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.distribution.DistributionRequest;
+
+/**
+ * Export options used to identify and process the resources to be extracted by {@link
+ * DistributionContentSerializer#exportToStream(ResourceResolver, DistributionExportOptions, OutputStream)}.
+ */
+public final class DistributionExportOptions {
+
+    private final DistributionRequest request;
+    private final DistributionExportFilter filter;
+
+    public DistributionExportOptions(DistributionRequest request, DistributionExportFilter filter) {
+        this.request = request;
+        this.filter = filter;
+    }
+
+    /**
+     * get the distribution request
+     * @return the distribution request
+     */
+    public DistributionRequest getRequest() {
+        return request;
+    }
+
+    /**
+     * get the export filter
+     * @return the export filter
+     */
+    public DistributionExportFilter getFilter() {
+        return filter;
+    }
+}

Propchange: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/DistributionExportOptions.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/DistributionPackageBuilderFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/DistributionPackageBuilderFactory.java?rev=1770942&r1=1770941&r2=1770942&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/DistributionPackageBuilderFactory.java (original)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/DistributionPackageBuilderFactory.java Wed Nov 23 10:22:05 2016
@@ -30,6 +30,7 @@ import org.apache.felix.scr.annotations.
 import org.apache.felix.scr.annotations.Deactivate;
 import org.apache.felix.scr.annotations.Property;
 import org.apache.felix.scr.annotations.PropertyOption;
+import org.apache.felix.scr.annotations.PropertyUnbounded;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.Service;
 import org.apache.sling.api.resource.ResourceResolver;
@@ -154,12 +155,27 @@ public class DistributionPackageBuilderF
     )
     private static final String MONITORING_QUEUE_SIZE = "monitoringQueueSize";
 
+    /**
+     * Package node filters
+     */
+    @Property(label = "Package Node Filters", description = "The package node path filters. Filter format: path|+include|-exclude", cardinality = 100)
+    private static final String PACKAGE_FILTERS = "package.filters";
+
+    /**
+     * Package property filters
+     */
+    @Property(label = "Package Property Filters", description = "The package property path filters. Filter format: path|+include|-exclude",
+            unbounded = PropertyUnbounded.ARRAY, value = {})
+    private static final String PROPERTY_FILTERS = "property.filters";
+
     private MonitoringDistributionPackageBuilder packageBuilder;
 
     @Activate
     public void activate(BundleContext context,
                          Map<String, Object> config) {
 
+        String[] nodeFilters = SettingsUtils.removeEmptyEntries(PropertiesUtil.toStringArray(config.get(PACKAGE_FILTERS), null));
+        String[] propertyFilters = SettingsUtils.removeEmptyEntries(PropertiesUtil.toStringArray(config.get(PROPERTY_FILTERS), null));
         String persistenceType = PropertiesUtil.toString(config.get(PERSISTENCE), null);
         String tempFsFolder = SettingsUtils.removeEmptyEntry(PropertiesUtil.toString(config.get(TEMP_FS_FOLDER), null));
         String digestAlgorithm = PropertiesUtil.toString(config.get(DIGEST_ALGORITHM), DEFAULT_DIGEST_ALGORITHM);
@@ -169,13 +185,13 @@ public class DistributionPackageBuilderF
 
         DistributionPackageBuilder wrapped;
         if ("file".equals(persistenceType)) {
-            wrapped = new FileDistributionPackageBuilder(contentSerializer.getName(), contentSerializer, tempFsFolder, digestAlgorithm);
+            wrapped = new FileDistributionPackageBuilder(contentSerializer.getName(), contentSerializer, tempFsFolder, digestAlgorithm, nodeFilters, propertyFilters);
         } else {
             final int fileThreshold = PropertiesUtil.toInteger(config.get(FILE_THRESHOLD), DEFAULT_FILE_THRESHOLD_VALUE);
             String memoryUnitName = PropertiesUtil.toString(config.get(MEMORY_UNIT), DEFAULT_MEMORY_UNIT);
             final MemoryUnit memoryUnit = MemoryUnit.valueOf(memoryUnitName);
             final boolean useOffHeapMemory = PropertiesUtil.toBoolean(config.get(USE_OFF_HEAP_MEMORY), DEFAULT_USE_OFF_HEAP_MEMORY);
-            wrapped = new ResourceDistributionPackageBuilder(contentSerializer.getName(), contentSerializer, tempFsFolder, fileThreshold, memoryUnit, useOffHeapMemory, digestAlgorithm);
+            wrapped = new ResourceDistributionPackageBuilder(contentSerializer.getName(), contentSerializer, tempFsFolder, fileThreshold, memoryUnit, useOffHeapMemory, digestAlgorithm, nodeFilters, propertyFilters);
         }
 
         int monitoringQueueSize = PropertiesUtil.toInteger(config.get(MONITORING_QUEUE_SIZE), DEFAULT_MONITORING_QUEUE_SIZE);

Modified: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/FileVaultContentSerializer.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/FileVaultContentSerializer.java?rev=1770942&r1=1770941&r2=1770942&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/FileVaultContentSerializer.java (original)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/FileVaultContentSerializer.java Wed Nov 23 10:22:05 2016
@@ -40,10 +40,10 @@ import org.apache.jackrabbit.vault.packa
 import org.apache.jackrabbit.vault.packaging.Packaging;
 import org.apache.jackrabbit.vault.packaging.VaultPackage;
 import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.distribution.DistributionRequest;
 import org.apache.sling.distribution.common.DistributionException;
-import org.apache.sling.distribution.serialization.DistributionContentSerializer;
 import org.apache.sling.distribution.packaging.impl.FileDistributionPackage;
+import org.apache.sling.distribution.serialization.DistributionContentSerializer;
+import org.apache.sling.distribution.serialization.DistributionExportOptions;
 import org.apache.sling.distribution.util.DistributionJcrUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -83,14 +83,14 @@ public class FileVaultContentSerializer
     }
 
     @Override
-    public void exportToStream(ResourceResolver resourceResolver, DistributionRequest request, OutputStream outputStream) throws DistributionException {
+    public void exportToStream(ResourceResolver resourceResolver, DistributionExportOptions exportOptions, OutputStream outputStream) throws DistributionException {
         Session session = null;
         try {
             session = getSession(resourceResolver);
             String packageGroup = PACKAGE_GROUP;
             String packageName = TYPE + "_" + System.currentTimeMillis() + "_" + UUID.randomUUID();
 
-            WorkspaceFilter filter = VltUtils.createFilter(request, nodeFilters, propertyFilters);
+            WorkspaceFilter filter = VltUtils.createFilter(exportOptions.getRequest(), nodeFilters, propertyFilters);
             ExportOptions opts = VltUtils.getExportOptions(filter, packageRoots, packageGroup, packageName, VERSION, useBinaryReferences);
 
             log.debug("assembling package {} user {}", packageGroup + '/' + packageName + "-" + VERSION, resourceResolver.getUserID());
@@ -172,4 +172,9 @@ public class FileVaultContentSerializer
     public String getName() {
         return name;
     }
+
+    @Override
+    public boolean isRequestFiltering() {
+        return true;
+    }
 }

Modified: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/VaultDistributionPackageBuilderFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/VaultDistributionPackageBuilderFactory.java?rev=1770942&r1=1770941&r2=1770942&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/VaultDistributionPackageBuilderFactory.java (original)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/VaultDistributionPackageBuilderFactory.java Wed Nov 23 10:22:05 2016
@@ -233,13 +233,13 @@ public class VaultDistributionPackageBui
 
         DistributionPackageBuilder wrapped;
         if ("filevlt".equals(type)) {
-            wrapped = new FileDistributionPackageBuilder(name, contentSerializer, tempFsFolder, digestAlgorithm);
+            wrapped = new FileDistributionPackageBuilder(name, contentSerializer, tempFsFolder, digestAlgorithm, packageNodeFilters, packagePropertyFilters);
         } else {
             final int fileThreshold = PropertiesUtil.toInteger(config.get(FILE_THRESHOLD), DEFAULT_FILE_THRESHOLD_VALUE);
             String memoryUnitName = PropertiesUtil.toString(config.get(MEMORY_UNIT), DEFAULT_MEMORY_UNIT);
             final MemoryUnit memoryUnit = MemoryUnit.valueOf(memoryUnitName);
             final boolean useOffHeapMemory = PropertiesUtil.toBoolean(config.get(USE_OFF_HEAP_MEMORY), DEFAULT_USE_OFF_HEAP_MEMORY);
-            wrapped = new ResourceDistributionPackageBuilder(contentSerializer.getName(), contentSerializer, tempFsFolder, fileThreshold, memoryUnit, useOffHeapMemory, digestAlgorithm);
+            wrapped = new ResourceDistributionPackageBuilder(contentSerializer.getName(), contentSerializer, tempFsFolder, fileThreshold, memoryUnit, useOffHeapMemory, digestAlgorithm, packageNodeFilters, packagePropertyFilters);
         }
 
         int monitoringQueueSize = PropertiesUtil.toInteger(config.get(MONITORING_QUEUE_SIZE), DEFAULT_MONITORING_QUEUE_SIZE);

Modified: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/VltUtils.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/VltUtils.java?rev=1770942&r1=1770941&r2=1770942&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/VltUtils.java (original)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/VltUtils.java Wed Nov 23 10:22:05 2016
@@ -146,7 +146,7 @@ public class VltUtils {
         props.setProperty(VaultPackage.NAME_GROUP, packageGroup);
         props.setProperty(VaultPackage.NAME_NAME, packageName);
         props.setProperty(VaultPackage.NAME_VERSION, packageVersion);
-    	props.setProperty(PackageProperties.NAME_USE_BINARY_REFERENCES, String.valueOf(useBinaryReferences));
+        props.setProperty(PackageProperties.NAME_USE_BINARY_REFERENCES, String.valueOf(useBinaryReferences));
         inf.setProperties(props);
 
         opts.setMetaInf(inf);
@@ -170,7 +170,6 @@ public class VltUtils {
             for (String currentRoot : packageRoots) {
                 boolean filtersHaveCommonRoot = true;
 
-
                 for (PathFilterSet filterSet : filterSets) {
                     String filterSetRoot = filterSet.getRoot();
 
@@ -184,16 +183,13 @@ public class VltUtils {
                     break;
                 }
             }
-
         }
 
-
         if (packageRoot == null || !packageRoot.startsWith("/")) {
             packageRoot = "/";
         }
 
         return packageRoot;
-
     }
 
     public static ImportOptions getImportOptions(AccessControlHandling aclHandling, ImportMode importMode, int autosaveThreshold) {
@@ -273,7 +269,7 @@ public class VltUtils {
     }
 
     public static File getTempFolder(String tempFolderPath) {
-        File directory = null;
+        File directory;
         try {
             directory = new File(tempFolderPath);
             if (!directory.exists() || !directory.isDirectory()) {
@@ -378,7 +374,7 @@ public class VltUtils {
     }
 
     private static PathFilterSet.Entry<DefaultPathFilter> extractPathPattern(String pattern) {
-        PathFilterSet.Entry<DefaultPathFilter> result = null;
+        PathFilterSet.Entry<DefaultPathFilter> result;
         if (pattern.startsWith("+")) {
             result = new PathFilterSet.Entry<DefaultPathFilter>(new DefaultPathFilter(pattern.substring(1)), true);
         } else if (pattern.startsWith("-")) {

Modified: sling/trunk/contrib/extensions/distribution/core/src/test/java/org/apache/sling/distribution/queue/impl/PriorityQueueDispatchingStrategyTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/test/java/org/apache/sling/distribution/queue/impl/PriorityQueueDispatchingStrategyTest.java?rev=1770942&r1=1770941&r2=1770942&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/test/java/org/apache/sling/distribution/queue/impl/PriorityQueueDispatchingStrategyTest.java (original)
+++ sling/trunk/contrib/extensions/distribution/core/src/test/java/org/apache/sling/distribution/queue/impl/PriorityQueueDispatchingStrategyTest.java Wed Nov 23 10:22:05 2016
@@ -16,10 +16,8 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-
 package org.apache.sling.distribution.queue.impl;
 
-
 import org.apache.sling.distribution.packaging.DistributionPackage;
 import org.apache.sling.distribution.packaging.DistributionPackageInfo;
 import org.apache.sling.distribution.packaging.impl.SharedDistributionPackage;

Added: sling/trunk/contrib/extensions/distribution/core/src/test/java/org/apache/sling/distribution/serialization/DistributionExportFilterTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/test/java/org/apache/sling/distribution/serialization/DistributionExportFilterTest.java?rev=1770942&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/test/java/org/apache/sling/distribution/serialization/DistributionExportFilterTest.java (added)
+++ sling/trunk/contrib/extensions/distribution/core/src/test/java/org/apache/sling/distribution/serialization/DistributionExportFilterTest.java Wed Nov 23 10:22:05 2016
@@ -0,0 +1,47 @@
+/*
+ * 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.distribution.serialization;
+
+import java.util.List;
+import java.util.NavigableMap;
+import java.util.TreeMap;
+
+import org.apache.sling.distribution.DistributionRequest;
+import org.apache.sling.distribution.DistributionRequestType;
+import org.apache.sling.distribution.SimpleDistributionRequest;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Tests for {@link DistributionExportFilter}
+ */
+public class DistributionExportFilterTest {
+
+    @Test
+    public void testCreateFilter() throws Exception {
+        DistributionRequest request = new SimpleDistributionRequest(DistributionRequestType.ADD, "/a", "/b");
+        NavigableMap<String, List<String>> nodeFilters = new TreeMap<String, List<String>>();
+        NavigableMap<String, List<String>> propertyFilters = new TreeMap<String, List<String>>();
+        DistributionExportFilter filter = DistributionExportFilter.createFilter(request, nodeFilters, propertyFilters);
+        assertNotNull(filter);
+        assertNotNull(filter.getNodeFilters());
+        assertNotNull(filter.getPropertyFilter());
+    }
+}
\ No newline at end of file

Propchange: sling/trunk/contrib/extensions/distribution/core/src/test/java/org/apache/sling/distribution/serialization/DistributionExportFilterTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/extensions/distribution/core/src/test/java/org/apache/sling/distribution/serialization/impl/vlt/FileVaultContentSerializerTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/test/java/org/apache/sling/distribution/serialization/impl/vlt/FileVaultContentSerializerTest.java?rev=1770942&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/test/java/org/apache/sling/distribution/serialization/impl/vlt/FileVaultContentSerializerTest.java (added)
+++ sling/trunk/contrib/extensions/distribution/core/src/test/java/org/apache/sling/distribution/serialization/impl/vlt/FileVaultContentSerializerTest.java Wed Nov 23 10:22:05 2016
@@ -0,0 +1,147 @@
+/*
+ * 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.distribution.serialization.impl.vlt;
+
+import javax.jcr.Session;
+import javax.jcr.Workspace;
+import javax.jcr.observation.ObservationManager;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.OutputStream;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.jackrabbit.vault.fs.api.ImportMode;
+import org.apache.jackrabbit.vault.fs.io.AccessControlHandling;
+import org.apache.jackrabbit.vault.packaging.ExportOptions;
+import org.apache.jackrabbit.vault.packaging.PackageManager;
+import org.apache.jackrabbit.vault.packaging.Packaging;
+import org.apache.jackrabbit.vault.packaging.VaultPackage;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.distribution.DistributionRequest;
+import org.apache.sling.distribution.serialization.DistributionExportFilter;
+import org.apache.sling.distribution.serialization.DistributionExportOptions;
+import org.apache.sling.testing.resourceresolver.MockHelper;
+import org.apache.sling.testing.resourceresolver.MockResourceResolverFactory;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.same;
+import static org.mockito.Mockito.*;
+
+/**
+ * Tests for {@link FileVaultContentSerializer}
+ */
+public class FileVaultContentSerializerTest {
+
+    private MockHelper helper;
+    private ResourceResolver resourceResolver;
+
+    @Before
+    public void setUp() throws Exception {
+        resourceResolver = new MockResourceResolverFactory().getResourceResolver(null);
+        helper = MockHelper.create(resourceResolver).resource("/libs").p("prop", "value")
+                .resource("sub").p("sub", "hello")
+                .resource(".sameLevel")
+                .resource("/apps").p("foo", "baa");
+        helper.commit();
+    }
+
+    @Test
+    public void testExportToStream() throws Exception {
+        Packaging packaging = mock(Packaging.class);
+
+        ImportMode importMode = ImportMode.REPLACE;
+        AccessControlHandling aclHandling = AccessControlHandling.IGNORE;
+
+        String[] packageRoots = new String[]{"/etc/packages"};
+        String[] nodeFilters = new String[0];
+        String[] propertyFilters = new String[0];
+        boolean useReferences = false;
+        int threshold = 1024;
+        FileVaultContentSerializer fileVaultContentSerializer = new FileVaultContentSerializer("vlt", packaging, importMode,
+                aclHandling, packageRoots, nodeFilters, propertyFilters, useReferences, threshold);
+
+        List<String> paths = new LinkedList<String>();
+        paths.add("/libs");
+        ResourceResolver sessionResolver = mock(ResourceResolver.class);
+        Session session = mock(Session.class);
+
+        PackageManager pm = mock(PackageManager.class);
+        when(packaging.getPackageManager()).thenReturn(pm);
+        OutputStream outputStream = new ByteArrayOutputStream();
+
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
+                return null;
+            }
+        }).when(pm).assemble(same(session), any(ExportOptions.class), same(outputStream));
+
+        Workspace workspace = mock(Workspace.class);
+        ObservationManager observationManager = mock(ObservationManager.class);
+        when(workspace.getObservationManager()).thenReturn(observationManager);
+        when(session.getWorkspace()).thenReturn(workspace);
+        when(sessionResolver.adaptTo(Session.class)).thenReturn(session);
+        DistributionExportFilter filter = mock(DistributionExportFilter.class);
+        DistributionRequest request = mock(DistributionRequest.class);
+        when(request.getPaths()).thenReturn(new String[]{"/libs"});
+        when(request.getFilters("/libs")).thenReturn(new String[0]);
+        DistributionExportOptions exportOptions = new DistributionExportOptions(request, filter);
+
+        fileVaultContentSerializer.exportToStream(sessionResolver, exportOptions, outputStream);
+    }
+
+    @Test
+    public void testImportFromStream() throws Exception {
+        Packaging packaging = mock(Packaging.class);
+        ImportMode importMode = ImportMode.REPLACE;
+        AccessControlHandling aclHandling = AccessControlHandling.IGNORE;
+
+        String[] packageRoots = new String[]{"/"};
+        String[] nodeFilters = new String[0];
+        String[] propertyFilters = new String[0];
+        boolean useReferences = false;
+        int thershold = 1024;
+        FileVaultContentSerializer fileVaultContentSerializer = new FileVaultContentSerializer("vlt", packaging, importMode,
+                aclHandling, packageRoots, nodeFilters, propertyFilters, useReferences, thershold);
+
+        ResourceResolver sessionResolver = mock(ResourceResolver.class);
+        Session session = mock(Session.class);
+
+        File file = new File(getClass().getResource("/vlt/dp.vlt").getFile());
+
+        PackageManager pm = mock(PackageManager.class);
+        VaultPackage vaultPackage = mock(VaultPackage.class);
+        when(pm.open(any(File.class))).thenReturn(vaultPackage);
+        when(packaging.getPackageManager()).thenReturn(pm);
+
+        Workspace workspace = mock(Workspace.class);
+        ObservationManager observationManager = mock(ObservationManager.class);
+        when(workspace.getObservationManager()).thenReturn(observationManager);
+        when(session.getWorkspace()).thenReturn(workspace);
+        when(sessionResolver.adaptTo(Session.class)).thenReturn(session);
+
+        fileVaultContentSerializer.importFromStream(sessionResolver, new FileInputStream(file));
+    }
+}
\ No newline at end of file

Propchange: sling/trunk/contrib/extensions/distribution/core/src/test/java/org/apache/sling/distribution/serialization/impl/vlt/FileVaultContentSerializerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/extensions/distribution/core/src/test/resources/vlt/dp.vlt
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/test/resources/vlt/dp.vlt?rev=1770942&view=auto
==============================================================================
Binary file - no diff available.

Propchange: sling/trunk/contrib/extensions/distribution/core/src/test/resources/vlt/dp.vlt
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/avro/AvroContentSerializer.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/avro/AvroContentSerializer.java?rev=1770942&r1=1770941&r2=1770942&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/avro/AvroContentSerializer.java (original)
+++ sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/avro/AvroContentSerializer.java Wed Nov 23 10:22:05 2016
@@ -28,15 +28,11 @@ import java.nio.ByteBuffer;
 import java.text.SimpleDateFormat;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.GregorianCalendar;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
-import java.util.regex.Pattern;
 
 import org.apache.avro.Schema;
 import org.apache.avro.file.DataFileReader;
@@ -49,14 +45,14 @@ import org.apache.avro.specific.Specific
 import org.apache.avro.specific.SpecificDatumWriter;
 import org.apache.avro.util.Utf8;
 import org.apache.commons.io.IOUtils;
-import org.apache.jackrabbit.JcrConstants;
 import org.apache.sling.api.resource.PersistenceException;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ValueMap;
-import org.apache.sling.distribution.DistributionRequest;
 import org.apache.sling.distribution.common.DistributionException;
 import org.apache.sling.distribution.serialization.DistributionContentSerializer;
+import org.apache.sling.distribution.serialization.DistributionExportFilter;
+import org.apache.sling.distribution.serialization.DistributionExportOptions;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -69,8 +65,6 @@ public class AvroContentSerializer imple
 
     private final String name;
     private final Schema schema;
-    private final Set<String> ignoredProperties;
-    private final Set<String> ignoredNodeNames;
     private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.sss+hh:mm");
 
     public AvroContentSerializer(String name) {
@@ -79,26 +73,11 @@ public class AvroContentSerializer imple
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
-        Set<String> iProps = new HashSet<String>();
-        iProps.add(JcrConstants.JCR_FROZENMIXINTYPES);
-        iProps.add(JcrConstants.JCR_FROZENPRIMARYTYPE);
-        iProps.add(JcrConstants.JCR_FROZENUUID);
-        iProps.add(JcrConstants.JCR_VERSIONHISTORY);
-        iProps.add(JcrConstants.JCR_BASEVERSION);
-        iProps.add(JcrConstants.JCR_PREDECESSORS);
-        iProps.add(JcrConstants.JCR_SUCCESSORS);
-        iProps.add(JcrConstants.JCR_ISCHECKEDOUT);
-        iProps.add(JcrConstants.JCR_UUID);
-        ignoredProperties = Collections.unmodifiableSet(iProps);
-
-        Set<String> iNames = new HashSet<String>();
-        iNames.add("rep:policy");
-        ignoredNodeNames = Collections.unmodifiableSet(iNames);
         this.name = name;
     }
 
     @Override
-    public void exportToStream(ResourceResolver resourceResolver, DistributionRequest request, OutputStream outputStream) throws DistributionException {
+    public void exportToStream(ResourceResolver resourceResolver, DistributionExportOptions options, OutputStream outputStream) throws DistributionException {
 
         DatumWriter<AvroShallowResource> datumWriter = new SpecificDatumWriter<AvroShallowResource>(AvroShallowResource.class);
         DataFileWriter<AvroShallowResource> writer = new DataFileWriter<AvroShallowResource>(datumWriter);
@@ -109,9 +88,12 @@ public class AvroContentSerializer imple
         }
 
         try {
-            for (String path : request.getPaths()) {
+            DistributionExportFilter filter = options.getFilter();
+            for (DistributionExportFilter.TreeFilter treeFilter : filter.getNodeFilters()) {
+                String path = treeFilter.getPath();
                 Resource resource = resourceResolver.getResource(path);
-                AvroShallowResource avroShallowResource = getAvroShallowResource(request, path, resource);
+                AvroShallowResource avroShallowResource = getAvroShallowResource(treeFilter, filter.getPropertyFilter(),
+                        resource);
                 writer.append(avroShallowResource);
             }
             outputStream.flush();
@@ -145,15 +127,23 @@ public class AvroContentSerializer imple
         return name;
     }
 
-    private AvroShallowResource getAvroShallowResource(DistributionRequest request, String path, Resource resource) throws IOException {
+    @Override
+    public boolean isRequestFiltering() {
+        return false;
+    }
+
+    private AvroShallowResource getAvroShallowResource(DistributionExportFilter.TreeFilter nodeFilter,
+                                                       DistributionExportFilter.TreeFilter propertyFilter,
+                                                       Resource resource) throws IOException {
         AvroShallowResource avroShallowResource = new AvroShallowResource();
         avroShallowResource.setName("avro_" + System.nanoTime());
-        avroShallowResource.setPath(path);
+        avroShallowResource.setPath(resource.getPath());
         avroShallowResource.setResourceType(resource.getResourceType());
         ValueMap valueMap = resource.getValueMap();
         Map<CharSequence, Object> map = new HashMap<CharSequence, Object>();
         for (Map.Entry<String, Object> entry : valueMap.entrySet()) {
-            if (!ignoredProperties.contains(entry.getKey())) {
+            String property = entry.getKey();
+            if (propertyFilter.matches(property)) {
                 Object value = entry.getValue();
                 if (value instanceof GregorianCalendar) {
                     value = dateFormat.format(((GregorianCalendar) value).getTime());
@@ -163,51 +153,20 @@ public class AvroContentSerializer imple
                 } else if (value instanceof InputStream) {
                     value = ByteBuffer.wrap(IOUtils.toByteArray(((InputStream) value)));
                 }
-                map.put(entry.getKey(), value);
+                map.put(property, value);
             }
         }
         avroShallowResource.setValueMap(map);
         List<AvroShallowResource> children = new LinkedList<AvroShallowResource>();
-        boolean deep = request.isDeep(path);
-        String[] filters = request.getFilters(path);
-        if (deep) {
-            for (Resource child : resource.getChildren()) {
-                String childPath = child.getPath();
-                if (!ignoredNodeNames.contains(child.getName())) {
-                    children.add(getAvroShallowResource(request, childPath, child));
-                }
-            }
-        } else {
-            for (Resource child : resource.getChildren()) {
-                String childPath = child.getPath();
-                if (filtersAllow(filters, childPath) && !ignoredNodeNames.contains(child.getName())) {
-                    children.add(getAvroShallowResource(request, childPath, child));
-                }
+        for (Resource child : resource.getChildren()) {
+            if (nodeFilter.matches(child.getPath())) {
+                children.add(getAvroShallowResource(nodeFilter, propertyFilter, child));
             }
         }
         avroShallowResource.setChildren(children);
         return avroShallowResource;
     }
 
-    private boolean filtersAllow(String[] filters, String path) {
-        boolean allowed = false;
-        for (String pattern : filters) {
-            if (pattern.startsWith("+")) {
-                if (Pattern.compile(pattern.substring(1)).matcher(path).matches()) {
-                    allowed = true;
-                }
-            } else if (pattern.startsWith("-")) {
-                if (Pattern.compile(pattern.substring(1)).matcher(path).matches()) {
-                    allowed = false;
-                }
-            } else {
-                allowed = Pattern.compile(pattern).matcher(path).matches();
-            }
-        }
-        return allowed;
-    }
-
-
     private Collection<AvroShallowResource> readAvroResources(byte[] bytes) throws IOException {
         DatumReader<AvroShallowResource> datumReader = new SpecificDatumReader<AvroShallowResource>(AvroShallowResource.class);
         DataFileReader<AvroShallowResource> dataFileReader = new DataFileReader<AvroShallowResource>(new SeekableByteArrayInput(bytes), datumReader);

Modified: sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/avro/AvroDistributionContentSerializerFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/avro/AvroDistributionContentSerializerFactory.java?rev=1770942&r1=1770941&r2=1770942&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/avro/AvroDistributionContentSerializerFactory.java (original)
+++ sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/avro/AvroDistributionContentSerializerFactory.java Wed Nov 23 10:22:05 2016
@@ -29,9 +29,9 @@ import org.apache.felix.scr.annotations.
 import org.apache.felix.scr.annotations.Service;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.commons.osgi.PropertiesUtil;
-import org.apache.sling.distribution.DistributionRequest;
 import org.apache.sling.distribution.common.DistributionException;
 import org.apache.sling.distribution.serialization.DistributionContentSerializer;
+import org.apache.sling.distribution.serialization.DistributionExportOptions;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -40,7 +40,7 @@ import org.slf4j.LoggerFactory;
  */
 @Component(metatype = true,
         label = "Apache Sling Distribution Packaging - Avro Serialization Format Factory",
-        description = "OSGi configuration for Avro serialization formats",
+        description = "OSGi configuration for Avro serializers",
         configurationFactory = true,
         specVersion = "1.1",
         policy = ConfigurationPolicy.REQUIRE
@@ -70,8 +70,8 @@ public class AvroDistributionContentSeri
 
 
     @Override
-    public void exportToStream(ResourceResolver resourceResolver, DistributionRequest request, OutputStream outputStream) throws DistributionException {
-        format.exportToStream(resourceResolver, request, outputStream);
+    public void exportToStream(ResourceResolver resourceResolver, DistributionExportOptions options, OutputStream outputStream) throws DistributionException {
+        format.exportToStream(resourceResolver, options, outputStream);
     }
 
     @Override
@@ -83,4 +83,9 @@ public class AvroDistributionContentSeri
     public String getName() {
         return format.getName();
     }
+
+    @Override
+    public boolean isRequestFiltering() {
+        return format.isRequestFiltering();
+    }
 }

Modified: sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/kryo/KryoContentSerializer.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/kryo/KryoContentSerializer.java?rev=1770942&r1=1770941&r2=1770942&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/kryo/KryoContentSerializer.java (original)
+++ sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/kryo/KryoContentSerializer.java Wed Nov 23 10:22:05 2016
@@ -19,33 +19,30 @@
 package org.apache.sling.distribution.serialization.impl.kryo;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.Map;
-import java.util.Set;
-import java.util.regex.Pattern;
 
 import com.esotericsoftware.kryo.Kryo;
 import com.esotericsoftware.kryo.Serializer;
 import com.esotericsoftware.kryo.io.Input;
 import com.esotericsoftware.kryo.io.Output;
 import org.apache.commons.io.IOUtils;
-import org.apache.jackrabbit.JcrConstants;
 import org.apache.sling.api.resource.PersistenceException;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.SyntheticResource;
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.api.wrappers.ValueMapDecorator;
-import org.apache.sling.distribution.DistributionRequest;
 import org.apache.sling.distribution.common.DistributionException;
 import org.apache.sling.distribution.serialization.DistributionContentSerializer;
+import org.apache.sling.distribution.serialization.DistributionExportFilter;
+import org.apache.sling.distribution.serialization.DistributionExportOptions;
 import org.objenesis.strategy.StdInstantiatorStrategy;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -58,43 +55,27 @@ public class KryoContentSerializer imple
     private final Logger log = LoggerFactory.getLogger(getClass());
 
     private final String name;
-    private final Set<String> ignoredProperties;
-    private final Set<String> ignoredNodeNames;
 
     public KryoContentSerializer(String name) {
         this.name = name;
-
-        Set<String> iProps = new HashSet<String>();
-        iProps.add(JcrConstants.JCR_FROZENMIXINTYPES);
-        iProps.add(JcrConstants.JCR_FROZENPRIMARYTYPE);
-        iProps.add(JcrConstants.JCR_FROZENUUID);
-        iProps.add(JcrConstants.JCR_VERSIONHISTORY);
-        iProps.add(JcrConstants.JCR_BASEVERSION);
-        iProps.add(JcrConstants.JCR_PREDECESSORS);
-        iProps.add(JcrConstants.JCR_SUCCESSORS);
-        iProps.add(JcrConstants.JCR_ISCHECKEDOUT);
-        iProps.add(JcrConstants.JCR_UUID);
-        ignoredProperties = Collections.unmodifiableSet(iProps);
-
-        Set<String> iNames = new HashSet<String>();
-        iNames.add("rep:policy");
-        ignoredNodeNames = Collections.unmodifiableSet(iNames);
     }
 
     @Override
-    public void exportToStream(ResourceResolver resourceResolver, DistributionRequest request, OutputStream outputStream) throws DistributionException {
+    public void exportToStream(ResourceResolver resourceResolver, DistributionExportOptions options, OutputStream outputStream) throws DistributionException {
+
+        DistributionExportFilter filter = options.getFilter();
 
         Kryo kryo = new Kryo();
         kryo.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));
-        kryo.addDefaultSerializer(Resource.class, new ResourceSerializer());
+        kryo.addDefaultSerializer(Resource.class, new ResourceSerializer(filter.getPropertyFilter()));
         kryo.addDefaultSerializer(InputStream.class, new InputStreamSerializer());
-        String[] paths = request.getPaths();
+
         Output output = new Output(outputStream);
         LinkedList<Resource> resources = new LinkedList<Resource>();
-        for (String p : paths) {
-            Resource resource = resourceResolver.getResource(p);
+        for (DistributionExportFilter.TreeFilter nodeFilter : filter.getNodeFilters()) {
+            Resource resource = resourceResolver.getResource(nodeFilter.getPath());
             if (resource != null) {
-                addResource(request, resources, resource);
+                addResource(nodeFilter, resources, resource);
             }
         }
         kryo.writeObject(output, resources);
@@ -106,7 +87,7 @@ public class KryoContentSerializer imple
     public void importFromStream(ResourceResolver resourceResolver, InputStream stream) throws DistributionException {
         Kryo kryo = new Kryo();
         kryo.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));
-        kryo.addDefaultSerializer(Resource.class, new ResourceSerializer());
+        kryo.addDefaultSerializer(Resource.class, new ResourceSerializer(null));
         kryo.addDefaultSerializer(InputStream.class, new InputStreamSerializer());
         try {
             Input input = new Input(stream);
@@ -126,6 +107,11 @@ public class KryoContentSerializer imple
         return name;
     }
 
+    @Override
+    public boolean isRequestFiltering() {
+        return false;
+    }
+
     private void persistResource(@Nonnull ResourceResolver resourceResolver, Resource resource) throws PersistenceException {
         String path = resource.getPath().trim();
         String name = path.substring(path.lastIndexOf('/') + 1);
@@ -156,6 +142,12 @@ public class KryoContentSerializer imple
 
     private class ResourceSerializer extends Serializer<Resource> {
 
+        private final DistributionExportFilter.TreeFilter propertyFilter;
+
+        private ResourceSerializer(@Nullable DistributionExportFilter.TreeFilter propertyFilter) {
+            this.propertyFilter = propertyFilter;
+        }
+
         @Override
         public void write(Kryo kryo, Output output, Resource resource) {
             ValueMap valueMap = resource.getValueMap();
@@ -165,7 +157,7 @@ public class KryoContentSerializer imple
 
             HashMap map = new HashMap<String, Object>();
             for (Map.Entry<String, Object> entry : valueMap.entrySet()) {
-                if (!ignoredProperties.contains(entry.getKey())) {
+                if (propertyFilter == null || propertyFilter.matches(entry.getKey())) {
                     map.put(entry.getKey(), entry.getValue());
                 }
             }
@@ -234,44 +226,15 @@ public class KryoContentSerializer imple
         }
     }
 
-    private void addResource(DistributionRequest request, LinkedList<Resource> resources, Resource resource) {
+    private void addResource(DistributionExportFilter.TreeFilter nodeFilter, LinkedList<Resource> resources, Resource resource) {
         resources.add(resource);
-        String path = resource.getPath();
-        boolean deep = request.isDeep(path);
-        String[] filters = request.getFilters(path);
-        if (deep) {
-            for (Resource child : resource.getChildren()) {
-                if (!ignoredNodeNames.contains(resource.getName())) {
-                    addResource(request, resources, child);
-                }
-            }
-        } else {
-            for (Resource child : resource.getChildren()) {
-                String childPath = child.getPath();
-                if (filtersAllow(filters, childPath) && !ignoredNodeNames.contains(child.getName())) {
-                    addResource(request, resources, child);
-                }
+        for (Resource child : resource.getChildren()) {
+            if (nodeFilter.matches(child.getPath())) {
+                addResource(nodeFilter, resources, child);
             }
         }
 
-    }
 
-    private boolean filtersAllow(String[] filters, String path) {
-        boolean allowed = false;
-        for (String pattern : filters) {
-            if (pattern.startsWith("+")) {
-                if (Pattern.compile(pattern.substring(1)).matcher(path).matches()) {
-                    allowed = true;
-                }
-            } else if (pattern.startsWith("-")) {
-                if (Pattern.compile(pattern.substring(1)).matcher(path).matches()) {
-                    allowed = false;
-                }
-            } else {
-                allowed = Pattern.compile(pattern).matcher(path).matches();
-            }
-        }
-        return allowed;
     }
 
 

Modified: sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/kryo/KryoDistributionContentSerializerFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/kryo/KryoDistributionContentSerializerFactory.java?rev=1770942&r1=1770941&r2=1770942&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/kryo/KryoDistributionContentSerializerFactory.java (original)
+++ sling/trunk/contrib/extensions/distribution/extensions/src/main/java/org/apache/sling/distribution/serialization/impl/kryo/KryoDistributionContentSerializerFactory.java Wed Nov 23 10:22:05 2016
@@ -29,9 +29,9 @@ import org.apache.felix.scr.annotations.
 import org.apache.felix.scr.annotations.Service;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.commons.osgi.PropertiesUtil;
-import org.apache.sling.distribution.DistributionRequest;
 import org.apache.sling.distribution.common.DistributionException;
 import org.apache.sling.distribution.serialization.DistributionContentSerializer;
+import org.apache.sling.distribution.serialization.DistributionExportOptions;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -40,7 +40,7 @@ import org.slf4j.LoggerFactory;
  */
 @Component(metatype = true,
         label = "Apache Sling Distribution Packaging - Kryo Serialization Format Factory",
-        description = "OSGi configuration for Kryo formatas",
+        description = "OSGi configuration for Kryo serializers",
         configurationFactory = true,
         specVersion = "1.1",
         policy = ConfigurationPolicy.REQUIRE
@@ -70,8 +70,8 @@ public class KryoDistributionContentSeri
 
 
     @Override
-    public void exportToStream(ResourceResolver resourceResolver, DistributionRequest request, OutputStream outputStream) throws DistributionException {
-        format.exportToStream(resourceResolver, request, outputStream);
+    public void exportToStream(ResourceResolver resourceResolver, DistributionExportOptions options, OutputStream outputStream) throws DistributionException {
+        format.exportToStream(resourceResolver, options, outputStream);
     }
 
     @Override
@@ -83,4 +83,9 @@ public class KryoDistributionContentSeri
     public String getName() {
         return format.getName();
     }
+
+    @Override
+    public boolean isRequestFiltering() {
+        return format.isRequestFiltering();
+    }
 }

Modified: sling/trunk/contrib/extensions/distribution/extensions/src/test/java/org/apache/sling/distribution/serialization/impl/avro/AvroContentSerializerTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/extensions/src/test/java/org/apache/sling/distribution/serialization/impl/avro/AvroContentSerializerTest.java?rev=1770942&r1=1770941&r2=1770942&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/extensions/src/test/java/org/apache/sling/distribution/serialization/impl/avro/AvroContentSerializerTest.java (original)
+++ sling/trunk/contrib/extensions/distribution/extensions/src/test/java/org/apache/sling/distribution/serialization/impl/avro/AvroContentSerializerTest.java Wed Nov 23 10:22:05 2016
@@ -20,11 +20,16 @@ package org.apache.sling.distribution.se
 
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
+import java.util.List;
+import java.util.NavigableMap;
+import java.util.TreeMap;
 
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.distribution.DistributionRequest;
 import org.apache.sling.distribution.DistributionRequestType;
 import org.apache.sling.distribution.SimpleDistributionRequest;
+import org.apache.sling.distribution.serialization.DistributionExportFilter;
+import org.apache.sling.distribution.serialization.DistributionExportOptions;
 import org.apache.sling.testing.resourceresolver.MockHelper;
 import org.apache.sling.testing.resourceresolver.MockResourceResolverFactory;
 import org.junit.Before;
@@ -52,14 +57,39 @@ public class AvroContentSerializerTest {
     }
 
     @Test
-    public void testExtract() throws Exception {
+    public void testExtractDeep() throws Exception {
+        AvroContentSerializer avroContentSerializer = new AvroContentSerializer("avro");
+        DistributionRequest request = new SimpleDistributionRequest(DistributionRequestType.ADD, true, "/libs");
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        NavigableMap<String, List<String>> nodeFilters = new TreeMap<String, List<String>>();
+        NavigableMap<String, List<String>> propertyFilters = new TreeMap<String, List<String>>();
+        try {
+            DistributionExportFilter filter = DistributionExportFilter.createFilter(request, nodeFilters, propertyFilters);
+            avroContentSerializer.exportToStream(resourceResolver, new DistributionExportOptions(request, filter), outputStream);
+            byte[] bytes = outputStream.toByteArray();
+            assertNotNull(bytes);
+            assertTrue(bytes.length > 0);
+        } finally {
+            outputStream.close();
+        }
+    }
+
+    @Test
+    public void testExtractShallow() throws Exception {
         AvroContentSerializer avroContentSerializer = new AvroContentSerializer("avro");
         DistributionRequest request = new SimpleDistributionRequest(DistributionRequestType.ADD, "/libs");
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-        avroContentSerializer.exportToStream(resourceResolver, request, outputStream);
-        byte[] bytes = outputStream.toByteArray();
-        assertNotNull(bytes);
-        assertTrue(bytes.length > 0);
+        NavigableMap<String, List<String>> nodeFilters = new TreeMap<String, List<String>>();
+        NavigableMap<String, List<String>> propertyFilters = new TreeMap<String, List<String>>();
+        try {
+            DistributionExportFilter filter = DistributionExportFilter.createFilter(request, nodeFilters, propertyFilters);
+            avroContentSerializer.exportToStream(resourceResolver, new DistributionExportOptions(request, filter), outputStream);
+            byte[] bytes = outputStream.toByteArray();
+            assertNotNull(bytes);
+            assertTrue(bytes.length > 0);
+        } finally {
+            outputStream.close();
+        }
     }
 
     @Test

Modified: sling/trunk/contrib/extensions/distribution/extensions/src/test/java/org/apache/sling/distribution/serialization/impl/kryo/KryoContentSerializerTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/extensions/src/test/java/org/apache/sling/distribution/serialization/impl/kryo/KryoContentSerializerTest.java?rev=1770942&r1=1770941&r2=1770942&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/extensions/src/test/java/org/apache/sling/distribution/serialization/impl/kryo/KryoContentSerializerTest.java (original)
+++ sling/trunk/contrib/extensions/distribution/extensions/src/test/java/org/apache/sling/distribution/serialization/impl/kryo/KryoContentSerializerTest.java Wed Nov 23 10:22:05 2016
@@ -20,13 +20,16 @@ package org.apache.sling.distribution.se
 
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
+import java.util.List;
+import java.util.NavigableMap;
+import java.util.TreeMap;
 
-import org.apache.commons.io.IOUtils;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.distribution.DistributionRequest;
 import org.apache.sling.distribution.DistributionRequestType;
 import org.apache.sling.distribution.SimpleDistributionRequest;
-import org.apache.sling.distribution.serialization.impl.avro.AvroContentSerializer;
+import org.apache.sling.distribution.serialization.DistributionExportFilter;
+import org.apache.sling.distribution.serialization.DistributionExportOptions;
 import org.apache.sling.testing.resourceresolver.MockHelper;
 import org.apache.sling.testing.resourceresolver.MockResourceResolverFactory;
 import org.junit.Before;
@@ -58,10 +61,17 @@ public class KryoContentSerializerTest {
         KryoContentSerializer kryoContentSerializer = new KryoContentSerializer("kryo");
         DistributionRequest request = new SimpleDistributionRequest(DistributionRequestType.ADD, "/libs");
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-        kryoContentSerializer.exportToStream(resourceResolver, request, outputStream);
-        byte[] bytes = outputStream.toByteArray();
-        assertNotNull(bytes);
-        assertTrue(bytes.length > 0);
+        NavigableMap<String, List<String>> nodeFilters = new TreeMap<String, List<String>>();
+        NavigableMap<String, List<String>> propertyFilters = new TreeMap<String, List<String>>();
+        try {
+            DistributionExportFilter filter = DistributionExportFilter.createFilter(request, nodeFilters, propertyFilters);
+            kryoContentSerializer.exportToStream(resourceResolver, new DistributionExportOptions(request, filter), outputStream);
+            byte[] bytes = outputStream.toByteArray();
+            assertNotNull(bytes);
+            assertTrue(bytes.length > 0);
+        } finally {
+            outputStream.close();
+        }
     }
 
     @Test