You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by kw...@apache.org on 2021/11/12 09:33:05 UTC

[jackrabbit-filevault] branch master updated: JCRVLT-549 - node cannot be deleted if it's a residual mandatory child node

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

kwin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jackrabbit-filevault.git


The following commit(s) were added to refs/heads/master by this push:
     new 3eb928d  JCRVLT-549 - node cannot be deleted if it's a residual mandatory child node
3eb928d is described below

commit 3eb928da8cbe21b42a2b5ed9bda8d72e1722856a
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Fri Nov 12 10:33:00 2021 +0100

    JCRVLT-549 - node cannot be deleted if it's a residual mandatory child node
    
    Co-authored-by: ankitaagar <an...@gmail.com>
    Co-authored-by: ankitaag <an...@adobe.com>
    Co-authored-by: Julian Reschke <ju...@gmx.de>
---
 .../vault/fs/impl/io/DocViewSAXImporter.java       |  52 +++++++++--
 .../apache/jackrabbit/vault/fs/io/AutoSave.java    |   7 +-
 .../packaging/integration/MandatoryNodeIT.java     | 100 +++++++++++++++++++++
 .../META-INF/MANIFEST.MF                           |   5 ++
 .../META-INF/vault/config.xml                      |  93 +++++++++++++++++++
 .../META-INF/vault/definition/.content.xml         |  24 +++++
 .../META-INF/vault/filter.xml                      |   4 +
 .../META-INF/vault/properties.xml                  |  19 ++++
 .../jcr_root/.content.xml                          |   6 ++
 .../wcm-rollout-config-1.zip/META-INF/MANIFEST.MF  |   5 ++
 .../META-INF/vault/config.xml                      |  93 +++++++++++++++++++
 .../META-INF/vault/definition/.content.xml         |  24 +++++
 .../META-INF/vault/filter.xml                      |   4 +
 .../META-INF/vault/nodetypes.cnd                   |  27 ++++++
 .../META-INF/vault/properties.xml                  |  19 ++++
 .../wcm-rollout-config-1.zip/jcr_root/.content.xml |   6 ++
 .../jcr_root/libs/.content.xml                     |   4 +
 .../jcr_root/libs/msm/.content.xml                 |   5 ++
 .../jcr_root/libs/msm/wcm/.content.xml             |   6 ++
 .../libs/msm/wcm/rolloutconfigs/.content.xml       |   9 ++
 .../msm/wcm/rolloutconfigs/activate/.content.xml   |   7 ++
 .../msm/wcm/rolloutconfigs/deactivate/.content.xml |   7 ++
 .../msm/wcm/rolloutconfigs/default/.content.xml    |  11 +++
 .../wcm-rollout-config-2.zip/META-INF/MANIFEST.MF  |   5 ++
 .../META-INF/vault/config.xml                      |  93 +++++++++++++++++++
 .../META-INF/vault/definition/.content.xml         |  24 +++++
 .../META-INF/vault/filter.xml                      |   4 +
 .../META-INF/vault/nodetypes.cnd                   |  26 ++++++
 .../META-INF/vault/properties.xml                  |  19 ++++
 .../wcm-rollout-config-2.zip/jcr_root/.content.xml |   6 ++
 .../jcr_root/libs/.content.xml                     |   4 +
 .../jcr_root/libs/msm/.content.xml                 |   5 ++
 .../jcr_root/libs/msm/wcm/.content.xml             |   6 ++
 .../libs/msm/wcm/rolloutconfigs/.content.xml       |   9 ++
 .../msm/wcm/rolloutconfigs/activate/.content.xml   |   7 ++
 .../msm/wcm/rolloutconfigs/deactivate/.content.xml |   6 ++
 .../msm/wcm/rolloutconfigs/default/.content.xml    |   9 ++
 37 files changed, 748 insertions(+), 12 deletions(-)

diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXImporter.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXImporter.java
index 9f29a60..00221ff 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXImporter.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXImporter.java
@@ -29,6 +29,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
+import java.util.Optional;
 
 import javax.jcr.ImportUUIDBehavior;
 import javax.jcr.Item;
@@ -46,6 +47,7 @@ import javax.jcr.Session;
 import javax.jcr.Value;
 import javax.jcr.ValueFactory;
 import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NodeDefinition;
 import javax.jcr.nodetype.NodeType;
 import javax.jcr.nodetype.PropertyDefinition;
 
@@ -994,7 +996,7 @@ public class DocViewSAXImporter extends RejectingEntityDefaultHandler implements
                     }
                 }
             }
-            
+
             // add/modify properties contained in package
             if (setUnprotectedProperties(node, ni, importMode == ImportMode.REPLACE|| importMode == ImportMode.UPDATE || importMode == ImportMode.UPDATE_PROPERTIES, vs)) {
                 updatedNode = node;
@@ -1040,7 +1042,7 @@ public class DocViewSAXImporter extends RejectingEntityDefaultHandler implements
             AttributesImpl attrs = new AttributesImpl();
             attrs.addAttribute(Name.NS_SV_URI, "name", "sv:name", "CDATA", ni.name);
             handler.startElement(Name.NS_SV_URI, "node", "sv:node", attrs);
-    
+
             // check if SNS and a helper uuid if needed
             boolean addMixRef = false;
             if (!ni.label.equals(ni.name) && ni.uuid == null) {
@@ -1098,7 +1100,6 @@ public class DocViewSAXImporter extends RejectingEntityDefaultHandler implements
                 node.removeMixin(JcrConstants.MIX_REFERENCEABLE);
             }
             return node;
-    
         } catch (SAXException e) {
             Exception root = e.getException();
             if (root instanceof RepositoryException) {
@@ -1263,13 +1264,29 @@ public class DocViewSAXImporter extends RejectingEntityDefaultHandler implements
                             }
                         } else {
                             if (wspFilter.getImportMode(path) == ImportMode.REPLACE) {
-                                importInfo.onDeleted(path);
+
+                                boolean shouldRemoveChild = true;
                                 // check if child is not protected
                                 if (child.getDefinition().isProtected()) {
-                                    log.debug("Refuse to delete protected child node: {}", path);
-                                } else if (child.getDefinition().isMandatory()) {
-                                    log.debug("Refuse to delete mandatory child node: {}", path);
-                                } else {
+                                    log.warn("Refuse to delete protected child node: {}", path);
+                                    shouldRemoveChild = false;
+                                    // check if child is mandatory (and not residual, https://s.apache.org/jcr-2.0-spec/2.0/3_Repository_Model.html#3.7.2.4%20Mandatory)
+                                } else if (child.getDefinition().isMandatory() && !child.getDefinition().getName().equals("*")) {
+                                    // get relevant child node definition from parent's effective node type
+                                    EffectiveNodeType ent = EffectiveNodeType.ofNode(child.getParent());
+                                    Optional<NodeDefinition> childNodeDefinition = ent.getApplicableChildNodeDefinition(child.getName(), child.getPrimaryNodeType());
+                                    if (!childNodeDefinition.isPresent()) {
+                                        // this should never happen as then child.getDefinition().isMandatory() would have returned false in the first place...
+                                        throw new IllegalStateException("Could not find applicable child node definition for mandatory child node " + child.getPath());
+                                    } else {
+                                        if (!hasSiblingWithPrimaryTypesAndName(child, childNodeDefinition.get().getRequiredPrimaryTypes(), childNodeDefinition.get().getName())) {
+                                            log.warn("Refuse to delete mandatory non-residual child node: {} with no other matching siblings", path);
+                                            shouldRemoveChild = false;
+                                        }
+                                    }
+                                } 
+                                if (shouldRemoveChild) {
+                                    importInfo.onDeleted(path);
                                     child.remove();
                                 }
                             }
@@ -1295,6 +1312,25 @@ public class DocViewSAXImporter extends RejectingEntityDefaultHandler implements
         }
     }
 
+    private boolean hasSiblingWithPrimaryTypesAndName(Node node, NodeType[] requiredPrimaryNodeTypes, String requiredName) throws RepositoryException {
+        NodeIterator iter = node.getParent().getNodes();
+        while (iter.hasNext()) {
+            Node sibling = iter.nextNode();
+            if (!sibling.isSame(node)) {
+                boolean allTypesMatch = true;
+                // check type: due to inheritance multiple primary node types need to be checked
+                for (NodeType requiredPrimaryNodeType : requiredPrimaryNodeTypes) {
+                    allTypesMatch &= sibling.isNodeType(requiredPrimaryNodeType.getName());
+                }
+                // check name
+                if (allTypesMatch && (requiredName.equals("*") || requiredName.equals(node.getName()))) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     /**
      * {@inheritDoc}
      */
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AutoSave.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AutoSave.java
index 6c7d23a..69d7109 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AutoSave.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AutoSave.java
@@ -168,8 +168,7 @@ public class AutoSave {
                 log.error(msg);
                 throw new RepositoryException(msg);
             }
-
-            if (!saveWithBackoff(session)) {
+            if (!saveWithBackoff(session, isIntermediate)) {
                 // either retry after some more nodes have been modified or after throttle 
                 // retry with next save() after another 10 nodes have been modified
                 failedSaveThreshold = 10;
@@ -186,7 +185,7 @@ public class AutoSave {
      * @return {@code true} in case was successful or {@code false} in case it failed with a potentially recoverable {@link RepositoryException}
      * @throws RepositoryException in case of unrecoverable exceptions
      */
-    private boolean saveWithBackoff(@NotNull Session session) throws RepositoryException {
+    private boolean saveWithBackoff(@NotNull Session session, boolean isIntermediate) throws RepositoryException {
         try {
             if (dryRun) {
                 session.refresh(false);
@@ -201,7 +200,7 @@ public class AutoSave {
                 debugSaveCount++;
             }
         } catch (RepositoryException e) {
-            if (isPotentiallyTransientException(e)) {
+            if (isPotentiallyTransientException(e) && isIntermediate) {
                 log.warn("could not auto-save due to potentially transient exception {}", e.getCause());
                 log.debug("auto save exception", e);
                 return false;
diff --git a/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/MandatoryNodeIT.java b/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/MandatoryNodeIT.java
new file mode 100644
index 0000000..559e7bf
--- /dev/null
+++ b/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/MandatoryNodeIT.java
@@ -0,0 +1,100 @@
+/*
+ * 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.jackrabbit.vault.packaging.integration;
+
+import java.io.IOException;
+
+import javax.jcr.ItemExistsException;
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.lock.LockException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.version.VersionException;
+
+import org.apache.jackrabbit.vault.packaging.PackageException;
+import org.junit.Assert;
+import org.junit.Test;
+
+
+public class MandatoryNodeIT extends IntegrationTestBase {
+ 
+    @Test
+    public void testMandatoryResidualChildNodesReplace()
+            throws RepositoryException, IOException, PackageException {
+
+        // some node types use both residual (name constraint = "*") and mandatory child nodes but according to
+        // JCR 2.0 (https://s.apache.org/jcr-2.0-spec/2.0/3_Repository_Model.html#3.7.2.4%20Mandatory)
+        // this is not allowed and is subsequently not enforced
+
+        // package set ups folder structure with mandatory child nodes
+        extractVaultPackage("/test-packages/wcm-rollout-config-1.zip");
+
+        assertNodeExists("/libs/msm/wcm/rolloutconfigs/activate/targetActivate");
+
+        assertNodeExists("/libs/msm/wcm/rolloutconfigs/deactivate/targetDeactivate");
+
+        assertNodeExists("/libs/msm/wcm/rolloutconfigs/default/contentUpdate");
+        assertNodeExists("/libs/msm/wcm/rolloutconfigs/default/contentCopy");
+        assertNodeExists("/libs/msm/wcm/rolloutconfigs/default/contentDelete");
+
+        // packages removes/replaces some mandatory child nodes
+        extractVaultPackage("/test-packages/wcm-rollout-config-2.zip");
+
+        // check if older nodes are replaced
+        assertNodeMissing("/libs/msm/wcm/rolloutconfigs/default/contentUpdate");
+        assertNodeMissing("/libs/msm/wcm/rolloutconfigs/default/contentDelete");
+        // check if newly added node exist
+        assertNodeExists("/libs/msm/wcm/rolloutconfigs/default/activate");
+        assertNodeExists("/libs/msm/wcm/rolloutconfigs/default/contentCopy");
+
+        // check if the only node is replaced
+        assertNodeMissing("/libs/msm/wcm/rolloutconfigs/activate/targetActivate");
+        assertNodeExists("/libs/msm/wcm/rolloutconfigs/activate/targetNewActivate");
+
+        // check if the only node is removed
+        assertNodeMissing("/libs/msm/wcm/rolloutconfigs/deactivate/targetDeactivate");
+    }
+
+    @Test
+    public void testMandatoryNonResidualChildNodesReplace() throws ItemExistsException, PathNotFoundException, NoSuchNodeTypeException, LockException, VersionException, ConstraintViolationException, RepositoryException, IOException, PackageException {
+        Node testnode = admin.getRootNode().addNode("testroot", NodeType.NT_FILE); // mandatory child node: jcr:content
+        try {
+            admin.save();
+            Assert.fail("Saving a node with a missing mandatory (but non-residual) child node must fail");
+        } catch (ConstraintViolationException e) {
+            // expected
+        }
+        testnode.addNode("jcr:content", "nt:unstructured"); 
+        admin.save();
+        
+        assertNodeExists("/testroot/jcr:content");
+        
+        // package tries to delete mandatory child node
+        try {
+            extractVaultPackage("/test-packages/mandatory-non-residual-childnode.zip");
+            Assert.fail("Deleting mandatory (but non-residual) child node must fail");
+        } catch (ConstraintViolationException e) {
+            // expected
+            admin.refresh(false);
+        }
+        assertNodeExists("/testroot/jcr:content");
+    }
+}
diff --git a/vault-core/src/test/resources/test-packages/mandatory-non-residual-childnode.zip/META-INF/MANIFEST.MF b/vault-core/src/test/resources/test-packages/mandatory-non-residual-childnode.zip/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..60c85a6
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/mandatory-non-residual-childnode.zip/META-INF/MANIFEST.MF
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+Content-Package-Roots: /libs/msm/wcm
+Content-Package-Type: application
+Content-Package-Id: my_packages:wcm-rollout-config:1
+
diff --git a/vault-core/src/test/resources/test-packages/mandatory-non-residual-childnode.zip/META-INF/vault/config.xml b/vault-core/src/test/resources/test-packages/mandatory-non-residual-childnode.zip/META-INF/vault/config.xml
new file mode 100644
index 0000000..b525f1c
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/mandatory-non-residual-childnode.zip/META-INF/vault/config.xml
@@ -0,0 +1,93 @@
+<!--
+  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.
+  -->
+<vaultfs version="1.1">
+    <!--
+        Defines the content aggregation. The order of the defined aggregates
+        is important for finding the correct aggregator.
+    -->
+    <aggregates>
+        <!--
+            Defines an aggregate that handles nt:file and nt:resource nodes.
+        -->
+        <aggregate type="file" title="File Aggregate"/>
+
+        <!--
+            Defines an aggregate that handles file/folder like nodes. It matches
+            all nt:hierarchyNode nodes that have or define a jcr:content
+            child node and excludes child nodes that are nt:hierarchyNodes.
+        -->
+        <aggregate type="filefolder" title="File/Folder Aggregate"/>
+
+        <!--
+            Defines an aggregate that handles nt:nodeType nodes and serializes
+            them into .cnd notation.
+        -->
+        <aggregate type="nodetype" title="Node Type Aggregate" />
+
+        <!--
+            Defines an aggregate that defines full coverage for certain node
+            types that cannot be covered by the default aggregator.
+        -->
+        <aggregate type="full" title="Full Coverage Aggregate">
+            <matches>
+                <include nodeType="rep:AccessControl" respectSupertype="true" />
+                <include nodeType="rep:Policy" respectSupertype="true" />
+                <include nodeType="cq:Widget" respectSupertype="true" />
+                <include nodeType="cq:EditConfig" respectSupertype="true" />
+                <include nodeType="cq:WorkflowModel" respectSupertype="true" />
+                <include nodeType="vlt:FullCoverage" respectSupertype="true" />
+                <include nodeType="mix:language" respectSupertype="true" />
+                <include nodeType="sling:OsgiConfig" respectSupertype="true" />
+            </matches>
+        </aggregate>
+
+        <!--
+            Defines an aggregate that handles nt:folder like nodes.
+        -->
+        <aggregate type="generic" title="Folder Aggregate">
+            <matches>
+                <include nodeType="nt:folder" respectSupertype="true" />
+            </matches>
+            <contains>
+                <exclude isNode="true" />
+            </contains>
+        </aggregate>
+
+        <!--
+            Defines the default aggregate
+        -->
+        <aggregate type="generic" title="Default Aggregator" isDefault="true">
+            <matches>
+                <!-- all -->
+            </matches>
+            <contains>
+                <exclude nodeType="nt:hierarchyNode" respectSupertype="true" />
+            </contains>
+        </aggregate>
+
+    </aggregates>
+
+    <!--
+      defines the input handlers
+    -->
+    <handlers>
+        <handler type="folder"/>
+        <handler type="file"/>
+        <handler type="nodetype"/>
+        <handler type="generic"/>
+    </handlers>
+</vaultfs>
diff --git a/vault-core/src/test/resources/test-packages/mandatory-non-residual-childnode.zip/META-INF/vault/definition/.content.xml b/vault-core/src/test/resources/test-packages/mandatory-non-residual-childnode.zip/META-INF/vault/definition/.content.xml
new file mode 100644
index 0000000..9c00456
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/mandatory-non-residual-childnode.zip/META-INF/vault/definition/.content.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:vlt="http://www.day.com/jcr/vault/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
+    jcr:created="{Date}2021-07-21T17:12:34.610+12:00"
+    jcr:createdBy="admin"
+    jcr:description=""
+    jcr:lastModified="{Date}2021-07-21T17:12:34.610+12:00"
+    jcr:lastModifiedBy="admin"
+    jcr:primaryType="vlt:PackageDefinition"
+    buildCount="1"
+    group="my_packages"
+    lastUnwrapped="{Date}2021-07-21T17:12:34.610+12:00"
+    lastUnwrappedBy="admin"
+    lastWrapped="{Date}2021-07-21T17:12:34.610+12:00"
+    lastWrappedBy="admin"
+    name="wcm-rollout-config"
+    version="2">
+    <filter jcr:primaryType="nt:unstructured">
+        <f0
+            jcr:primaryType="nt:unstructured"
+            mode="replace"
+            root="/libs/msm/wcm"
+            rules="[]"/>
+    </filter>
+</jcr:root>
diff --git a/vault-core/src/test/resources/test-packages/mandatory-non-residual-childnode.zip/META-INF/vault/filter.xml b/vault-core/src/test/resources/test-packages/mandatory-non-residual-childnode.zip/META-INF/vault/filter.xml
new file mode 100644
index 0000000..0d4f8b3
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/mandatory-non-residual-childnode.zip/META-INF/vault/filter.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<workspaceFilter version="1.0">
+    <filter root="/testroot/jcr:content"/>
+</workspaceFilter>
diff --git a/vault-core/src/test/resources/test-packages/mandatory-non-residual-childnode.zip/META-INF/vault/properties.xml b/vault-core/src/test/resources/test-packages/mandatory-non-residual-childnode.zip/META-INF/vault/properties.xml
new file mode 100644
index 0000000..00866f7
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/mandatory-non-residual-childnode.zip/META-INF/vault/properties.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+<comment>FileVault Package Properties</comment>
+<entry key="createdBy">admin</entry>
+<entry key="name">wcm-rollout-config</entry>
+<entry key="lastModified">2021-07-21T17:12:34.610+12:00</entry>
+<entry key="lastModifiedBy">admin</entry>
+<entry key="created">2021-07-21T17:12:34.623+12:00</entry>
+<entry key="buildCount">1</entry>
+<entry key="version">2</entry>
+<entry key="packageType">application</entry>
+<entry key="dependencies"/>
+<entry key="packageFormatVersion">2</entry>
+<entry key="description"/>
+<entry key="lastWrapped">2021-07-21T17:12:34.610+12:00</entry>
+<entry key="group">my_packages</entry>
+<entry key="lastWrappedBy">admin</entry>
+</properties>
diff --git a/vault-core/src/test/resources/test-packages/mandatory-non-residual-childnode.zip/jcr_root/.content.xml b/vault-core/src/test/resources/test-packages/mandatory-non-residual-childnode.zip/jcr_root/.content.xml
new file mode 100644
index 0000000..8ea9f2a
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/mandatory-non-residual-childnode.zip/jcr_root/.content.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+    jcr:mixinTypes="[rep:AccessControllable,rep:RepoAccessControllable]"
+    jcr:primaryType="rep:root"
+    sling:resourceType="sling:redirect"
+    sling:target="/index.html"/>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/META-INF/MANIFEST.MF b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..60c85a6
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/META-INF/MANIFEST.MF
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+Content-Package-Roots: /libs/msm/wcm
+Content-Package-Type: application
+Content-Package-Id: my_packages:wcm-rollout-config:1
+
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/META-INF/vault/config.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/META-INF/vault/config.xml
new file mode 100644
index 0000000..b525f1c
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/META-INF/vault/config.xml
@@ -0,0 +1,93 @@
+<!--
+  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.
+  -->
+<vaultfs version="1.1">
+    <!--
+        Defines the content aggregation. The order of the defined aggregates
+        is important for finding the correct aggregator.
+    -->
+    <aggregates>
+        <!--
+            Defines an aggregate that handles nt:file and nt:resource nodes.
+        -->
+        <aggregate type="file" title="File Aggregate"/>
+
+        <!--
+            Defines an aggregate that handles file/folder like nodes. It matches
+            all nt:hierarchyNode nodes that have or define a jcr:content
+            child node and excludes child nodes that are nt:hierarchyNodes.
+        -->
+        <aggregate type="filefolder" title="File/Folder Aggregate"/>
+
+        <!--
+            Defines an aggregate that handles nt:nodeType nodes and serializes
+            them into .cnd notation.
+        -->
+        <aggregate type="nodetype" title="Node Type Aggregate" />
+
+        <!--
+            Defines an aggregate that defines full coverage for certain node
+            types that cannot be covered by the default aggregator.
+        -->
+        <aggregate type="full" title="Full Coverage Aggregate">
+            <matches>
+                <include nodeType="rep:AccessControl" respectSupertype="true" />
+                <include nodeType="rep:Policy" respectSupertype="true" />
+                <include nodeType="cq:Widget" respectSupertype="true" />
+                <include nodeType="cq:EditConfig" respectSupertype="true" />
+                <include nodeType="cq:WorkflowModel" respectSupertype="true" />
+                <include nodeType="vlt:FullCoverage" respectSupertype="true" />
+                <include nodeType="mix:language" respectSupertype="true" />
+                <include nodeType="sling:OsgiConfig" respectSupertype="true" />
+            </matches>
+        </aggregate>
+
+        <!--
+            Defines an aggregate that handles nt:folder like nodes.
+        -->
+        <aggregate type="generic" title="Folder Aggregate">
+            <matches>
+                <include nodeType="nt:folder" respectSupertype="true" />
+            </matches>
+            <contains>
+                <exclude isNode="true" />
+            </contains>
+        </aggregate>
+
+        <!--
+            Defines the default aggregate
+        -->
+        <aggregate type="generic" title="Default Aggregator" isDefault="true">
+            <matches>
+                <!-- all -->
+            </matches>
+            <contains>
+                <exclude nodeType="nt:hierarchyNode" respectSupertype="true" />
+            </contains>
+        </aggregate>
+
+    </aggregates>
+
+    <!--
+      defines the input handlers
+    -->
+    <handlers>
+        <handler type="folder"/>
+        <handler type="file"/>
+        <handler type="nodetype"/>
+        <handler type="generic"/>
+    </handlers>
+</vaultfs>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/META-INF/vault/definition/.content.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/META-INF/vault/definition/.content.xml
new file mode 100644
index 0000000..9c00456
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/META-INF/vault/definition/.content.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:vlt="http://www.day.com/jcr/vault/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
+    jcr:created="{Date}2021-07-21T17:12:34.610+12:00"
+    jcr:createdBy="admin"
+    jcr:description=""
+    jcr:lastModified="{Date}2021-07-21T17:12:34.610+12:00"
+    jcr:lastModifiedBy="admin"
+    jcr:primaryType="vlt:PackageDefinition"
+    buildCount="1"
+    group="my_packages"
+    lastUnwrapped="{Date}2021-07-21T17:12:34.610+12:00"
+    lastUnwrappedBy="admin"
+    lastWrapped="{Date}2021-07-21T17:12:34.610+12:00"
+    lastWrappedBy="admin"
+    name="wcm-rollout-config"
+    version="2">
+    <filter jcr:primaryType="nt:unstructured">
+        <f0
+            jcr:primaryType="nt:unstructured"
+            mode="replace"
+            root="/libs/msm/wcm"
+            rules="[]"/>
+    </filter>
+</jcr:root>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/META-INF/vault/filter.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/META-INF/vault/filter.xml
new file mode 100644
index 0000000..19770ed
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/META-INF/vault/filter.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<workspaceFilter version="1.0">
+    <filter root="/libs/msm/wcm"/>
+</workspaceFilter>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/META-INF/vault/nodetypes.cnd b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/META-INF/vault/nodetypes.cnd
new file mode 100644
index 0000000..09bcebd
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/META-INF/vault/nodetypes.cnd
@@ -0,0 +1,27 @@
+<'sling'='http://sling.apache.org/jcr/sling/1.0'>
+<'nt'='http://www.jcp.org/jcr/nt/1.0'>
+<'cq'='http://www.day.com/jcr/cq/1.0'>
+<'mix'='http://www.jcp.org/jcr/mix/1.0'>
+<'rep'='internal'>
+
+[sling:OrderedFolder] > sling:Folder
+  orderable
+  + * (nt:base) = sling:OrderedFolder version
+
+[sling:Folder] > nt:folder
+  - * (undefined) multiple
+  - * (undefined)
+  + * (nt:base) = sling:Folder version
+
+[cq:RolloutConfig] > mix:title
+  orderable
+  - cq:trigger (string) mandatory
+  + * (cq:LiveSyncAction) mandatory
+
+[cq:LiveSyncAction] > nt:unstructured
+
+
+[rep:RepoAccessControllable]
+  mixin
+  + rep:repoPolicy (rep:Policy) protected ignore
+
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/META-INF/vault/properties.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/META-INF/vault/properties.xml
new file mode 100644
index 0000000..00866f7
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/META-INF/vault/properties.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+<comment>FileVault Package Properties</comment>
+<entry key="createdBy">admin</entry>
+<entry key="name">wcm-rollout-config</entry>
+<entry key="lastModified">2021-07-21T17:12:34.610+12:00</entry>
+<entry key="lastModifiedBy">admin</entry>
+<entry key="created">2021-07-21T17:12:34.623+12:00</entry>
+<entry key="buildCount">1</entry>
+<entry key="version">2</entry>
+<entry key="packageType">application</entry>
+<entry key="dependencies"/>
+<entry key="packageFormatVersion">2</entry>
+<entry key="description"/>
+<entry key="lastWrapped">2021-07-21T17:12:34.610+12:00</entry>
+<entry key="group">my_packages</entry>
+<entry key="lastWrappedBy">admin</entry>
+</properties>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/.content.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/.content.xml
new file mode 100644
index 0000000..8ea9f2a
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/.content.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+    jcr:mixinTypes="[rep:AccessControllable,rep:RepoAccessControllable]"
+    jcr:primaryType="rep:root"
+    sling:resourceType="sling:redirect"
+    sling:target="/index.html"/>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/.content.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/.content.xml
new file mode 100644
index 0000000..792d2ea
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/.content.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" xmlns:rep="internal"
+    jcr:mixinTypes="[rep:AccessControllable]"
+    jcr:primaryType="nt:folder"/>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/msm/.content.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/msm/.content.xml
new file mode 100644
index 0000000..3db28fb
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/msm/.content.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+    jcr:mixinTypes="[rep:AccessControllable]"
+    jcr:primaryType="sling:Folder"
+    jcr:title="MSM"/>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/msm/wcm/.content.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/msm/wcm/.content.xml
new file mode 100644
index 0000000..b4b6de5
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/msm/wcm/.content.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+    jcr:mixinTypes="[rep:AccessControllable]"
+    jcr:primaryType="sling:OrderedFolder">
+    <rolloutconfigs/>
+</jcr:root>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/msm/wcm/rolloutconfigs/.content.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/msm/wcm/rolloutconfigs/.content.xml
new file mode 100644
index 0000000..d12ffce
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/msm/wcm/rolloutconfigs/.content.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+    jcr:mixinTypes="[rep:AccessControllable]"
+    jcr:primaryType="sling:OrderedFolder"
+    jcr:title="Rollout Configurations">
+    <default/>
+    <activate/>
+    <deactivate/>
+</jcr:root>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/msm/wcm/rolloutconfigs/activate/.content.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/msm/wcm/rolloutconfigs/activate/.content.xml
new file mode 100644
index 0000000..d7a36aa
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/msm/wcm/rolloutconfigs/activate/.content.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
+    cq:trigger="publish"
+    jcr:primaryType="cq:RolloutConfig"
+    jcr:title="Activate on Blueprint activation">
+    <targetActivate jcr:primaryType="cq:LiveSyncAction"/>
+</jcr:root>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/msm/wcm/rolloutconfigs/deactivate/.content.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/msm/wcm/rolloutconfigs/deactivate/.content.xml
new file mode 100644
index 0000000..3f2bcb2
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/msm/wcm/rolloutconfigs/deactivate/.content.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
+    cq:trigger="deactivate"
+    jcr:primaryType="cq:RolloutConfig"
+    jcr:title="Deactivate on Blueprint deactivation">
+    <targetDeactivate jcr:primaryType="cq:LiveSyncAction"/>
+</jcr:root>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/msm/wcm/rolloutconfigs/default/.content.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/msm/wcm/rolloutconfigs/default/.content.xml
new file mode 100644
index 0000000..057cdf3
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-1.zip/jcr_root/libs/msm/wcm/rolloutconfigs/default/.content.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
+    cq:trigger="rollout"
+    jcr:description="Standard rollout configuration which allows to start rollout process on rollout trigger and runs actions: create, update, delete content and order children nodes."
+    jcr:primaryType="cq:RolloutConfig"
+    jcr:title="Standard rollout config">
+    <contentUpdate jcr:primaryType="cq:LiveSyncAction"/>
+    <activate jcr:primaryType="cq:LiveSyncAction"/>
+    <contentCopy jcr:primaryType="cq:LiveSyncAction"/>
+    <contentDelete jcr:primaryType="cq:LiveSyncAction"/>
+</jcr:root>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/META-INF/MANIFEST.MF b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..60c85a6
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/META-INF/MANIFEST.MF
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+Content-Package-Roots: /libs/msm/wcm
+Content-Package-Type: application
+Content-Package-Id: my_packages:wcm-rollout-config:1
+
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/META-INF/vault/config.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/META-INF/vault/config.xml
new file mode 100644
index 0000000..b525f1c
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/META-INF/vault/config.xml
@@ -0,0 +1,93 @@
+<!--
+  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.
+  -->
+<vaultfs version="1.1">
+    <!--
+        Defines the content aggregation. The order of the defined aggregates
+        is important for finding the correct aggregator.
+    -->
+    <aggregates>
+        <!--
+            Defines an aggregate that handles nt:file and nt:resource nodes.
+        -->
+        <aggregate type="file" title="File Aggregate"/>
+
+        <!--
+            Defines an aggregate that handles file/folder like nodes. It matches
+            all nt:hierarchyNode nodes that have or define a jcr:content
+            child node and excludes child nodes that are nt:hierarchyNodes.
+        -->
+        <aggregate type="filefolder" title="File/Folder Aggregate"/>
+
+        <!--
+            Defines an aggregate that handles nt:nodeType nodes and serializes
+            them into .cnd notation.
+        -->
+        <aggregate type="nodetype" title="Node Type Aggregate" />
+
+        <!--
+            Defines an aggregate that defines full coverage for certain node
+            types that cannot be covered by the default aggregator.
+        -->
+        <aggregate type="full" title="Full Coverage Aggregate">
+            <matches>
+                <include nodeType="rep:AccessControl" respectSupertype="true" />
+                <include nodeType="rep:Policy" respectSupertype="true" />
+                <include nodeType="cq:Widget" respectSupertype="true" />
+                <include nodeType="cq:EditConfig" respectSupertype="true" />
+                <include nodeType="cq:WorkflowModel" respectSupertype="true" />
+                <include nodeType="vlt:FullCoverage" respectSupertype="true" />
+                <include nodeType="mix:language" respectSupertype="true" />
+                <include nodeType="sling:OsgiConfig" respectSupertype="true" />
+            </matches>
+        </aggregate>
+
+        <!--
+            Defines an aggregate that handles nt:folder like nodes.
+        -->
+        <aggregate type="generic" title="Folder Aggregate">
+            <matches>
+                <include nodeType="nt:folder" respectSupertype="true" />
+            </matches>
+            <contains>
+                <exclude isNode="true" />
+            </contains>
+        </aggregate>
+
+        <!--
+            Defines the default aggregate
+        -->
+        <aggregate type="generic" title="Default Aggregator" isDefault="true">
+            <matches>
+                <!-- all -->
+            </matches>
+            <contains>
+                <exclude nodeType="nt:hierarchyNode" respectSupertype="true" />
+            </contains>
+        </aggregate>
+
+    </aggregates>
+
+    <!--
+      defines the input handlers
+    -->
+    <handlers>
+        <handler type="folder"/>
+        <handler type="file"/>
+        <handler type="nodetype"/>
+        <handler type="generic"/>
+    </handlers>
+</vaultfs>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/META-INF/vault/definition/.content.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/META-INF/vault/definition/.content.xml
new file mode 100644
index 0000000..9c00456
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/META-INF/vault/definition/.content.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:vlt="http://www.day.com/jcr/vault/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
+    jcr:created="{Date}2021-07-21T17:12:34.610+12:00"
+    jcr:createdBy="admin"
+    jcr:description=""
+    jcr:lastModified="{Date}2021-07-21T17:12:34.610+12:00"
+    jcr:lastModifiedBy="admin"
+    jcr:primaryType="vlt:PackageDefinition"
+    buildCount="1"
+    group="my_packages"
+    lastUnwrapped="{Date}2021-07-21T17:12:34.610+12:00"
+    lastUnwrappedBy="admin"
+    lastWrapped="{Date}2021-07-21T17:12:34.610+12:00"
+    lastWrappedBy="admin"
+    name="wcm-rollout-config"
+    version="2">
+    <filter jcr:primaryType="nt:unstructured">
+        <f0
+            jcr:primaryType="nt:unstructured"
+            mode="replace"
+            root="/libs/msm/wcm"
+            rules="[]"/>
+    </filter>
+</jcr:root>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/META-INF/vault/filter.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/META-INF/vault/filter.xml
new file mode 100644
index 0000000..19770ed
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/META-INF/vault/filter.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<workspaceFilter version="1.0">
+    <filter root="/libs/msm/wcm"/>
+</workspaceFilter>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/META-INF/vault/nodetypes.cnd b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/META-INF/vault/nodetypes.cnd
new file mode 100644
index 0000000..ee941ee
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/META-INF/vault/nodetypes.cnd
@@ -0,0 +1,26 @@
+<'sling'='http://sling.apache.org/jcr/sling/1.0'>
+<'nt'='http://www.jcp.org/jcr/nt/1.0'>
+<'cq'='http://www.day.com/jcr/cq/1.0'>
+<'mix'='http://www.jcp.org/jcr/mix/1.0'>
+<'rep'='internal'>
+
+[sling:OrderedFolder] > sling:Folder
+  orderable
+  + * (nt:base) = sling:OrderedFolder version
+
+[sling:Folder] > nt:folder
+  - * (undefined) multiple
+  - * (undefined)
+  + * (nt:base) = sling:Folder version
+
+[cq:RolloutConfig] > mix:title
+  orderable
+  - cq:trigger (string) mandatory
+  + * (cq:LiveSyncAction) mandatory  
+
+[cq:LiveSyncAction] > nt:unstructured
+
+[rep:RepoAccessControllable]
+  mixin
+  + rep:repoPolicy (rep:Policy) protected ignore
+
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/META-INF/vault/properties.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/META-INF/vault/properties.xml
new file mode 100644
index 0000000..00866f7
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/META-INF/vault/properties.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+<comment>FileVault Package Properties</comment>
+<entry key="createdBy">admin</entry>
+<entry key="name">wcm-rollout-config</entry>
+<entry key="lastModified">2021-07-21T17:12:34.610+12:00</entry>
+<entry key="lastModifiedBy">admin</entry>
+<entry key="created">2021-07-21T17:12:34.623+12:00</entry>
+<entry key="buildCount">1</entry>
+<entry key="version">2</entry>
+<entry key="packageType">application</entry>
+<entry key="dependencies"/>
+<entry key="packageFormatVersion">2</entry>
+<entry key="description"/>
+<entry key="lastWrapped">2021-07-21T17:12:34.610+12:00</entry>
+<entry key="group">my_packages</entry>
+<entry key="lastWrappedBy">admin</entry>
+</properties>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/.content.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/.content.xml
new file mode 100644
index 0000000..8ea9f2a
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/.content.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+    jcr:mixinTypes="[rep:AccessControllable,rep:RepoAccessControllable]"
+    jcr:primaryType="rep:root"
+    sling:resourceType="sling:redirect"
+    sling:target="/index.html"/>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/.content.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/.content.xml
new file mode 100644
index 0000000..792d2ea
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/.content.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" xmlns:rep="internal"
+    jcr:mixinTypes="[rep:AccessControllable]"
+    jcr:primaryType="nt:folder"/>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/msm/.content.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/msm/.content.xml
new file mode 100644
index 0000000..3db28fb
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/msm/.content.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+    jcr:mixinTypes="[rep:AccessControllable]"
+    jcr:primaryType="sling:Folder"
+    jcr:title="MSM"/>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/msm/wcm/.content.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/msm/wcm/.content.xml
new file mode 100644
index 0000000..b4b6de5
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/msm/wcm/.content.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+    jcr:mixinTypes="[rep:AccessControllable]"
+    jcr:primaryType="sling:OrderedFolder">
+    <rolloutconfigs/>
+</jcr:root>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/msm/wcm/rolloutconfigs/.content.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/msm/wcm/rolloutconfigs/.content.xml
new file mode 100644
index 0000000..d12ffce
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/msm/wcm/rolloutconfigs/.content.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+    jcr:mixinTypes="[rep:AccessControllable]"
+    jcr:primaryType="sling:OrderedFolder"
+    jcr:title="Rollout Configurations">
+    <default/>
+    <activate/>
+    <deactivate/>
+</jcr:root>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/msm/wcm/rolloutconfigs/activate/.content.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/msm/wcm/rolloutconfigs/activate/.content.xml
new file mode 100644
index 0000000..dfefc66
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/msm/wcm/rolloutconfigs/activate/.content.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
+    cq:trigger="publish"
+    jcr:primaryType="cq:RolloutConfig"
+    jcr:title="Activate on Blueprint activation">
+    <targetNewActivate jcr:primaryType="cq:LiveSyncAction"/>
+</jcr:root>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/msm/wcm/rolloutconfigs/deactivate/.content.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/msm/wcm/rolloutconfigs/deactivate/.content.xml
new file mode 100644
index 0000000..5f6c6c4
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/msm/wcm/rolloutconfigs/deactivate/.content.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
+    cq:trigger="deactivate"
+    jcr:primaryType="cq:RolloutConfig"
+    jcr:title="Deactivate on Blueprint deactivation">
+</jcr:root>
diff --git a/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/msm/wcm/rolloutconfigs/default/.content.xml b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/msm/wcm/rolloutconfigs/default/.content.xml
new file mode 100644
index 0000000..566e29a
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/wcm-rollout-config-2.zip/jcr_root/libs/msm/wcm/rolloutconfigs/default/.content.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
+    cq:trigger="rollout"
+    jcr:description="Standard rollout configuration which allows to start rollout process on rollout trigger and runs actions: create, update, delete content and order children nodes."
+    jcr:primaryType="cq:RolloutConfig"
+    jcr:title="Standard rollout config">
+    <activate jcr:primaryType="cq:LiveSyncAction"/>
+    <contentCopy jcr:primaryType="cq:LiveSyncAction"/>
+</jcr:root>