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

svn commit: r1816018 [1/2] - in /jackrabbit/commons/filevault/trunk: parent/ vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/ vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/ vault-core/src/main/java/org/apache/jackrabbit/vaul...

Author: tripod
Date: Wed Nov 22 09:30:11 2017
New Revision: 1816018

URL: http://svn.apache.org/viewvc?rev=1816018&view=rev
Log:
JCRVLT-208 Add support for package storage outside /etc/packages

Added:
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/CompositeExportProcessor.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/SubPackageExportProcessor.java
Modified:
    jackrabbit/commons/filevault/trunk/parent/pom.xml
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/DefaultWorkspaceFilter.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/Importer.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackagingService.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageDefinitionImpl.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageImpl.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImpl.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/PackageManagerImpl.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/PackageManagerMBeanImpl.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/PackagingImpl.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/ZipVaultPackage.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/JcrPackageRegistry.java
    jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImplTest.java
    jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/ImportTests.java
    jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/IntegrationTestBase.java
    jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestArchiveExtraction.java
    jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestNoRootAccessExport.java
    jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestPackageCreation.java
    jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestPackageInstall.java
    jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestPackageRegistry.java
    jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestSubPackages.java

Modified: jackrabbit/commons/filevault/trunk/parent/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/parent/pom.xml?rev=1816018&r1=1816017&r2=1816018&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/parent/pom.xml (original)
+++ jackrabbit/commons/filevault/trunk/parent/pom.xml Wed Nov 22 09:30:11 2017
@@ -162,7 +162,7 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-surefire-plugin</artifactId>
-                    <version>2.4.2</version>
+                    <version>2.20.1</version>
                     <configuration>
                         <systemProperties>
                             <property>

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/DefaultWorkspaceFilter.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/DefaultWorkspaceFilter.java?rev=1816018&r1=1816017&r2=1816018&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/DefaultWorkspaceFilter.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/DefaultWorkspaceFilter.java Wed Nov 22 09:30:11 2017
@@ -235,6 +235,7 @@ public class DefaultWorkspaceFilter impl
             return this;
         }
         DefaultWorkspaceFilter mapped = new DefaultWorkspaceFilter();
+        mapped.importMode = importMode;
         if (globalIgnored != null) {
             mapped.setGlobalIgnored(globalIgnored.translate(mapping));
         }

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/Importer.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/Importer.java?rev=1816018&r1=1816017&r2=1816018&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/Importer.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/Importer.java Wed Nov 22 09:30:11 2017
@@ -665,7 +665,7 @@ public class Importer {
                     }
                 }
                 // todo: find better way to detect sub-packages
-                if (repoPath.startsWith(JcrPackageRegistry.PACKAGE_ROOT_PATH_PREFIX) && (repoPath.endsWith(".jar") || repoPath.endsWith(".zip"))) {
+                if (repoPath.startsWith(JcrPackageRegistry.DEFAULT_PACKAGE_ROOT_PATH_PREFIX) && (repoPath.endsWith(".jar") || repoPath.endsWith(".zip"))) {
                     subPackages.add(repoPath);
                 }
 

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackagingService.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackagingService.java?rev=1816018&r1=1816017&r2=1816018&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackagingService.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackagingService.java Wed Nov 22 09:30:11 2017
@@ -24,6 +24,8 @@ import javax.jcr.Session;
 import org.apache.jackrabbit.vault.packaging.impl.JcrPackageDefinitionImpl;
 import org.apache.jackrabbit.vault.packaging.impl.JcrPackageManagerImpl;
 import org.apache.jackrabbit.vault.packaging.impl.PackageManagerImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Default access point to package managers for non OSGi clients.
@@ -33,6 +35,11 @@ import org.apache.jackrabbit.vault.packa
 public class PackagingService {
 
     /**
+     * default logger
+     */
+    private static final Logger log = LoggerFactory.getLogger(PackagingService.class);
+
+    /**
      * Returns a non-repository based package manager.
      * @return the package manager
      */
@@ -46,7 +53,14 @@ public class PackagingService {
      * @return the package manager
      */
     public static JcrPackageManager getPackageManager(Session session) {
-        return new JcrPackageManagerImpl(session);
+        try {
+            throw new IllegalStateException();
+        } catch (IllegalStateException e) {
+            log.warn("JcrPackageManager acquired w/o service! Alternate package roots will not be respected.", e);
+        }
+
+        // todo: should somehow pass the package roots
+        return new JcrPackageManagerImpl(session, new String[0]);
     }
 
     /**

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/CompositeExportProcessor.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/CompositeExportProcessor.java?rev=1816018&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/CompositeExportProcessor.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/CompositeExportProcessor.java Wed Nov 22 09:30:11 2017
@@ -0,0 +1,43 @@
+/*
+ * 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.impl;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.jackrabbit.vault.fs.io.AbstractExporter;
+import org.apache.jackrabbit.vault.packaging.ExportPostProcessor;
+
+/**
+ * Helper class that allows to chain post processors.
+ */
+public class CompositeExportProcessor implements ExportPostProcessor {
+
+    private List<ExportPostProcessor> processors = new LinkedList<>();
+
+    public void addProcessor(ExportPostProcessor p) {
+        processors.add(p);
+    }
+
+    @Override
+    public void process(AbstractExporter exporter) {
+        for (ExportPostProcessor p: processors) {
+            p.process(exporter);
+        }
+    }
+}

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageDefinitionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageDefinitionImpl.java?rev=1816018&r1=1816017&r2=1816018&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageDefinitionImpl.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageDefinitionImpl.java Wed Nov 22 09:30:11 2017
@@ -19,7 +19,9 @@ package org.apache.jackrabbit.vault.pack
 
 import java.io.IOException;
 import java.net.URISyntaxException;
+import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.Collection;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Properties;
@@ -873,6 +875,37 @@ public class JcrPackageDefinitionImpl im
     }
 
     /**
+     * Returns the list of sub packages set on the definition node via the {@link #PN_SUB_PACKAGES} property.
+     * @return the list of sub package ids
+     * @throws RepositoryException if an error occurs.
+     */
+    protected List<PackageId> getSubPackages() throws RepositoryException {
+        LinkedList<PackageId> subPackages = new LinkedList<PackageId>();
+        if (defNode.hasProperty(PN_SUB_PACKAGES)) {
+            Value[] subIds = defNode.getProperty(PN_SUB_PACKAGES).getValues();
+            for (Value v : subIds) {
+                // reverse installation order
+                subPackages.add(PackageId.fromString(v.getString()));
+            }
+        }
+        return subPackages;
+    }
+
+    /**
+     * Sets the package Ids to the definition node
+     * @param subPackageIds the package Ids
+     * @throws RepositoryException if an error occurs
+     */
+    protected void setSubPackages(Collection<PackageId> subPackageIds) throws RepositoryException {
+        String[] subIds = new String[subPackageIds.size()];
+        int i =0;
+        for (PackageId subId: subPackageIds) {
+            subIds[i++] = subId.toString();
+        }
+        defNode.setProperty(PN_SUB_PACKAGES, subIds);
+    }
+
+    /**
      * Returns a new state object that can be used to save modification information.
      * @return a new state object.
      */

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageImpl.java?rev=1816018&r1=1816017&r2=1816018&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageImpl.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageImpl.java Wed Nov 22 09:30:11 2017
@@ -38,7 +38,6 @@ import javax.jcr.Node;
 import javax.jcr.Property;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
-import javax.jcr.Value;
 import javax.jcr.nodetype.NodeTypeManager;
 
 import org.apache.commons.io.FileUtils;
@@ -80,6 +79,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import static org.apache.jackrabbit.vault.packaging.impl.JcrPackageManagerImpl.ARCHIVE_PACKAGE_ROOT_PATH;
+import static org.apache.jackrabbit.vault.packaging.registry.impl.JcrPackageRegistry.DEFAULT_PACKAGE_ROOT_PATH;
 
 /**
  * Implements a JcrPackage
@@ -222,32 +222,12 @@ public class JcrPackageImpl implements J
 
     /**
      * {@inheritDoc}
+     *
+     * @return {@code true} always.
      */
+    @Deprecated
     public boolean verifyId(boolean autoFix, boolean autoSave) throws RepositoryException {
-        // check if package id is correct
-        JcrPackageDefinition jDef = getDefinition();
-        if (jDef == null) {
-            return true;
-        }
-        if (node == null) {
-            return false;
-        }
-        PackageId id = jDef.getId();
-        PackageId cId = new PackageId(node.getPath());
-        // compare installation paths since non-conform version numbers might
-        // lead to different pids (bug #35564)
-        if (JcrPackageRegistry.getInstallationPath(id).equals(JcrPackageRegistry.getInstallationPath(cId))) {
-            if (autoFix && id.isFromPath()) {
-                // if definition has no id set, fix anyways
-                jDef.setId(cId, autoSave);
-            }
-            return true;
-        }
-        if (autoFix) {
-            log.warn("Fixing non-matching id from {} to {}.", id, cId);
-            jDef.setId(cId, autoSave);
-        }
-        return false;
+        return true;
     }
 
 
@@ -435,8 +415,28 @@ public class JcrPackageImpl implements J
                     }
                 }
                 if (p.isValid()) {
-                    // ensure that sub package is marked as not-installed. it might contain wrong data in vlt:definition (JCRVLT-114)
                     JcrPackageDefinitionImpl def = (JcrPackageDefinitionImpl) p.getDefinition();
+                    PackageId pId = def.getId();
+
+                    // check if package is at the correct location
+                    String expectedPath = mgr.getInstallationPath(pId) + ".zip";
+                    if (!expectedPath.equals(path)) {
+                        if (s.nodeExists(expectedPath)) {
+                            log.info("(Removed duplicated sub-package in {}. Still present at {}", path, expectedPath);
+                            s.getNode(path).remove();
+                            s.save();
+                        } else {
+                            log.info("Moving sub-package in place: {} -> {}", path, expectedPath);
+                            s.getWorkspace().move(path, expectedPath);
+                        }
+                        path = expectedPath;
+                        // re-acquire the package and definition
+                        p.close();
+                        p = new JcrPackageImpl(mgr, s.getNode(path));
+                        def = (JcrPackageDefinitionImpl) p.getDefinition();
+                    }
+
+                    // ensure that sub package is marked as not-installed. it might contain wrong data in vlt:definition (JCRVLT-114)
                     def.clearLastUnpacked(false);
 
                     // add dependency to the parent package if required
@@ -446,12 +446,11 @@ public class JcrPackageImpl implements J
                         def.setDependencies(newDeps, false);
                     }
 
-                    PackageId pId = def.getId();
                     String pName = pId.getName();
                     Version pVersion = pId.getVersion();
 
                     // get the list of packages available in the same group
-                    JcrPackageManager pkgMgr = new JcrPackageManagerImpl(s);                    
+                    JcrPackageManager pkgMgr = new JcrPackageManagerImpl(s, mgr.getPackRootPaths()); // todo: use registry instead ?
                     List<JcrPackage> listPackages = pkgMgr.listPackages(pId.getGroup(), true);
 
                     // keep some status variable if a more recent is found in the next loop
@@ -495,7 +494,7 @@ public class JcrPackageImpl implements J
                     throw e;
                 }
             }
-            List<String> subIds = new LinkedList<String>();
+            List<PackageId> subIds = new LinkedList<PackageId>();
             SubPackageHandling sb = pack.getSubPackageHandling();
             for (JcrPackageImpl p: subPacks) {
                 boolean skip = false;
@@ -521,18 +520,21 @@ public class JcrPackageImpl implements J
                 if (!skip) {
                     if (createSnapshot && option == SubPackageHandling.Option.INSTALL) {
                         p.extract(options, true, true);
-                        subIds.add(id.toString());
+                        subIds.add(id);
                     } else {
                         p.extract(options, false, true);
                     }
                 }
                 p.close();
             }
-            // register sub packages in snapshot for uninstall
+            // register sub packages in snapshot and on package for uninstall
             if (snap != null) {
-                snap.getDefinition().getNode().setProperty(JcrPackageDefinition.PN_SUB_PACKAGES, subIds.toArray(new String[subIds.size()]));
-                s.save();
+                ((JcrPackageDefinitionImpl) snap.getDefinition()).setSubPackages(subIds);
             }
+            if (def != null) {
+                def.setSubPackages(subIds);
+            }
+            s.save();
         }
 
         if (createSnapshot) {
@@ -577,7 +579,7 @@ public class JcrPackageImpl implements J
         boolean hasOwnContent = false;
         for (PathFilterSet root: a.getMetaInf().getFilter().getFilterSets()) {
             // todo: find better way to detect subpackages
-            if (!Text.isDescendantOrEqual(JcrPackageRegistry.PACKAGE_ROOT_PATH, root.getRoot())) {
+            if (!Text.isDescendantOrEqual(DEFAULT_PACKAGE_ROOT_PATH, root.getRoot())) {
                 log.debug("Package {}: contains content outside /etc/packages. Sub packages will have a dependency to it", pId);
                 hasOwnContent = true;
                 break;
@@ -849,7 +851,7 @@ public class JcrPackageImpl implements J
             return null;
         }
         PackageId id = getSnapshotId();
-        Node packNode = getPackageNode(id);
+        Node packNode = getSnapshotNode();
         if (packNode != null) {
             if (!replace) {
                 log.debug("Refusing to recreate snapshot {}, already exists.", id);
@@ -873,8 +875,8 @@ public class JcrPackageImpl implements J
         }
         
         log.debug("Creating snapshot for {}.", id);
-        JcrPackageManagerImpl packMgr = new JcrPackageManagerImpl(node.getSession());
-        String path = JcrPackageRegistry.getInstallationPath(id);
+        JcrPackageManagerImpl packMgr = new JcrPackageManagerImpl(node.getSession(), mgr.getPackRootPaths());
+        String path = mgr.getInstallationPath(id);
         String parentPath = Text.getRelativeParent(path, 1);
         Node folder = packMgr.mkdir(parentPath, true);
         JcrPackage snap = mgr.createNew(folder, id, null, true);
@@ -897,17 +899,16 @@ public class JcrPackageImpl implements J
     }
 
     /**
-     * Returns the package node of the given package id.
-     * @param id the package id
+     * Returns the snapshot package node of this package
      * @return the package node
      * @throws RepositoryException if an error occurs
      */
     @CheckForNull
-    private Node getPackageNode(PackageId id) throws RepositoryException {
+    private Node getSnapshotNode() throws RepositoryException {
         if (node == null) {
             return null;
         }
-        String path = JcrPackageRegistry.getInstallationPath(id);
+        String path = node.getParent().getPath() + "/.snapshot/" + node.getName();
         if (node.getSession().nodeExists(path)) {
             return node.getSession().getNode(path);
         } else if (node.getSession().nodeExists(path + ".zip")) {
@@ -920,8 +921,7 @@ public class JcrPackageImpl implements J
      * {@inheritDoc}
      */
     public JcrPackage getSnapshot() throws RepositoryException {
-        PackageId id = getSnapshotId();
-        Node packNode = getPackageNode(id);
+        Node packNode = getSnapshotNode();
         if (packNode != null) {
             JcrPackageImpl snap = new JcrPackageImpl(mgr, packNode);
             if (snap.isValid()) {
@@ -971,6 +971,10 @@ public class JcrPackageImpl implements J
         }
 
         JcrPackage snap = getSnapshot();
+        List<PackageId> subPackages = snap == null
+                ? def.getSubPackages()
+                : ((JcrPackageDefinitionImpl) snap.getDefinition()).getSubPackages();
+
         if (snap == null) {
             if (opts.isStrict()) {
                 throw new PackageException("Unable to uninstall package. No snapshot present.");
@@ -983,29 +987,17 @@ public class JcrPackageImpl implements J
         } else {
             Session s = getNode().getSession();
             // check for recursive uninstall
-            if (!opts.isNonRecursive()) {
-                Node defNode = snap.getDefNode();
-                LinkedList<PackageId> subPackages = new LinkedList<PackageId>();
-                if (defNode.hasProperty(JcrPackageDefinition.PN_SUB_PACKAGES)) {
-                    Value[] subIds = defNode.getProperty(JcrPackageDefinition.PN_SUB_PACKAGES).getValues();
-                    for (Value v : subIds) {
-                        // reverse installation order
-                        subPackages.addLast(PackageId.fromString(v.getString()));
-                    }
-                }
-                if (subPackages.size() > 0) {
-                    JcrPackageManagerImpl packMgr = new JcrPackageManagerImpl(s);
-                    for (PackageId id : subPackages) {
-                        JcrPackage pack = packMgr.open(id);
-                        if (pack != null) {
-                            if (pack.getSnapshot() == null) {
-                                log.warn("Unable to uninstall sub package {}. Snapshot missing.", id);
-                            } else {
-                                pack.uninstall(opts);
-                            }
+            if (!opts.isNonRecursive() && subPackages.size() > 0) {
+                JcrPackageManagerImpl packMgr = new JcrPackageManagerImpl(s, mgr.getPackRootPaths());
+                for (PackageId id : subPackages) {
+                    JcrPackage pack = packMgr.open(id);
+                    if (pack != null) {
+                        if (pack.getSnapshot() == null) {
+                            log.warn("Unable to uninstall sub package {}. Snapshot missing.", id);
+                        } else {
+                            pack.uninstall(opts);
                         }
                     }
-
                 }
             }
 
@@ -1019,6 +1011,15 @@ public class JcrPackageImpl implements J
             s.save();
         }
 
+        // uninstallation always removes the sub-packages, unless non-recursive and snapshot missing
+        if (!opts.isNonRecursive() || snap != null) {
+            for (PackageId id : subPackages) {
+                if (mgr.contains(id)) {
+                    mgr.remove(id);
+                }
+            }
+        }
+
         // revert installed flags on this package
         JcrPackageDefinitionImpl def = (JcrPackageDefinitionImpl) getDefinition();
         def.clearLastUnpacked(true);

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImpl.java?rev=1816018&r1=1816017&r2=1816018&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImpl.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImpl.java Wed Nov 22 09:30:11 2017
@@ -40,6 +40,7 @@ import javax.jcr.Session;
 import org.apache.commons.io.FileUtils;
 import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener;
 import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
+import org.apache.jackrabbit.vault.fs.config.DefaultMetaInf;
 import org.apache.jackrabbit.vault.fs.impl.ArchiveWrapper;
 import org.apache.jackrabbit.vault.fs.impl.SubPackageFilterArchive;
 import org.apache.jackrabbit.vault.fs.io.Archive;
@@ -61,6 +62,8 @@ import org.apache.jackrabbit.vault.packa
 import org.apache.jackrabbit.vault.packaging.registry.impl.JcrRegisteredPackage;
 import org.apache.jackrabbit.vault.util.JcrConstants;
 
+import static org.apache.jackrabbit.vault.packaging.registry.impl.JcrPackageRegistry.DEFAULT_PACKAGE_ROOT_PATH;
+
 /**
  * Extends the {@code PackageManager} by JCR specific methods
  */
@@ -77,12 +80,17 @@ public class JcrPackageManagerImpl exten
     private final JcrPackageRegistry registry;
 
     /**
-     * Creates a new package manager using the given session.
+     * Creates a new package manager using the given session. This method allows to specify one more or package
+     * registry root paths, where the first will be the primary when installing new packages. The others server as
+     * backward compatibility to read existing packages.
      *
      * @param session repository session
+     * @param roots the root paths to store the packages.
+     *
+     * @see JcrPackageRegistry(Session, String ...)
      */
-    public JcrPackageManagerImpl(Session session) {
-        this(new JcrPackageRegistry(session));
+    public JcrPackageManagerImpl(Session session, String[] roots) {
+        this(new JcrPackageRegistry(session, roots));
     }
 
     private JcrPackageManagerImpl(JcrPackageRegistry registry) {
@@ -96,6 +104,9 @@ public class JcrPackageManagerImpl exten
         return new RepositoryException(e);
     }
 
+    public JcrPackageRegistry getRegistry() {
+        return registry;
+    }
 
     /**
      * {@inheritDoc}
@@ -322,10 +333,24 @@ public class JcrPackageManagerImpl exten
         validateSubPackages(def);
         def.sealForAssembly(now, true);
 
+        DefaultMetaInf inf = (DefaultMetaInf) def.getMetaInf();
+        CompositeExportProcessor processor = new CompositeExportProcessor();
+
+        // tweak filter for primary root, in case it contains sub-packages
+        if (!registry.getPackRootPaths()[0].equals(DEFAULT_PACKAGE_ROOT_PATH)) {
+            SubPackageExportProcessor sp = new SubPackageExportProcessor(this, packNode.getSession());
+            WorkspaceFilter newFilter = sp.prepare(inf.getFilter());
+            if (newFilter != null) {
+                inf.setFilter(newFilter);
+                processor.addProcessor(sp);
+            }
+        }
+
         ExportOptions opts = new ExportOptions();
-        opts.setMetaInf(def.getMetaInf());
+        opts.setMetaInf(inf);
         opts.setListener(listener);
-        opts.setPostProcessor(def.getInjectProcessor());
+        processor.addProcessor(def.getInjectProcessor());
+        opts.setPostProcessor(processor);
 
         VaultPackage pack = assemble(packNode.getSession(), opts, (File) null);
         PackageId id = pack.getId();
@@ -441,7 +466,7 @@ public class JcrPackageManagerImpl exten
      */
     @Override
     public Node getPackageRoot() throws RepositoryException {
-        return registry.getPackageRoot(false);
+        return registry.getPrimaryPackageRoot(true);
     }
 
     /**
@@ -449,7 +474,7 @@ public class JcrPackageManagerImpl exten
      */
     @Override
     public Node getPackageRoot(boolean noCreate) throws RepositoryException {
-        return registry.getPackageRoot(noCreate);
+        return registry.getPrimaryPackageRoot(!noCreate);
     }
 
     /**
@@ -465,15 +490,12 @@ public class JcrPackageManagerImpl exten
      */
     @Override
     public List<JcrPackage> listPackages(WorkspaceFilter filter) throws RepositoryException {
-        Node root = getPackageRoot(true);
-        if (root == null) {
-            return Collections.emptyList();
-        } else {
-            List<JcrPackage> packages = new LinkedList<JcrPackage>();
+        List<JcrPackage> packages = new LinkedList<JcrPackage>();
+        for (Node root: registry.getPackageRoots()) {
             listPackages(root, packages, filter, false, false);
-            Collections.sort(packages);
-            return packages;
         }
+        Collections.sort(packages);
+        return packages;
     }
 
     /**
@@ -481,36 +503,45 @@ public class JcrPackageManagerImpl exten
      */
     @Override
     public List<JcrPackage> listPackages(String group, boolean built) throws RepositoryException {
-        Node pRoot = getPackageRoot(true);
-        if (pRoot == null) {
-            return Collections.emptyList();
-        }
         List<JcrPackage> packages = new LinkedList<JcrPackage>();
-        if (group == null) {
-            listPackages(pRoot, packages, null, built, false);
+        for (Node root: registry.getPackageRoots()) {
+            listPackages(root, packages, group, built);
+        }
+        Collections.sort(packages);
+        return packages;
+    }
+
+    /**
+     * internally lists all the packages below the given package root and adds them to the given list.
+     * @param pkgRoot the package root
+     * @param packages the list of packages
+     * @param group optional group to search below
+     * @param built if {@code true} only packages with size > 0 are returned
+     * @throws RepositoryException if an error occurrs
+     */
+    private void listPackages(Node pkgRoot, List<JcrPackage> packages, String group, boolean built) throws RepositoryException {
+        if (group == null || group.length() == 0) {
+            listPackages(pkgRoot, packages, null, built, false);
         } else {
-            Node root = pRoot;
+            if (group.equals(pkgRoot.getPath())) {
+                group = "";
+            } else if (group.startsWith(pkgRoot.getPath() + "/")) {
+                group = group.substring(pkgRoot.getPath().length() + 1);
+            }
+            if (group.startsWith("/")) {
+                // don't scan outside the roots
+                return;
+            }
+            Node root = pkgRoot;
             if (group.length() > 0) {
-                if (group.equals(pRoot.getPath())) {
-                    group = "";
-                } else if (group.startsWith(pRoot.getPath() + "/")) {
-                    group = group.substring(pRoot.getPath().length() + 1);
-                }
-                if (group.startsWith("/")) {
-                    // don't scan outside /etc/packages
-                    return packages;
-                } else if (group.length() > 0) {
-                    if (root.hasNode(group)) {
-                        root = root.getNode(group);
-                    } else {
-                        return packages;
-                    }
+                if (root.hasNode(group)) {
+                    root = root.getNode(group);
+                } else {
+                    return;
                 }
             }
             listPackages(root, packages, null, built, true);
         }
-        Collections.sort(packages);
-        return packages;
     }
 
     /**

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/PackageManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/PackageManagerImpl.java?rev=1816018&r1=1816017&r2=1816018&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/PackageManagerImpl.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/PackageManagerImpl.java Wed Nov 22 09:30:11 2017
@@ -37,10 +37,13 @@ import javax.jcr.Session;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.jackrabbit.vault.fs.Mounter;
+import org.apache.jackrabbit.vault.fs.api.PathFilterSet;
 import org.apache.jackrabbit.vault.fs.api.RepositoryAddress;
 import org.apache.jackrabbit.vault.fs.api.VaultFileSystem;
 import org.apache.jackrabbit.vault.fs.api.VaultFsConfig;
+import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
 import org.apache.jackrabbit.vault.fs.config.DefaultMetaInf;
+import org.apache.jackrabbit.vault.fs.config.DefaultWorkspaceFilter;
 import org.apache.jackrabbit.vault.fs.config.MetaInf;
 import org.apache.jackrabbit.vault.fs.impl.AggregateManagerImpl;
 import org.apache.jackrabbit.vault.fs.io.JarExporter;
@@ -54,6 +57,9 @@ import org.apache.jackrabbit.vault.packa
 import org.apache.jackrabbit.vault.packaging.events.impl.PackageEventDispatcher;
 import org.apache.jackrabbit.vault.util.Constants;
 
+import static org.apache.jackrabbit.vault.packaging.registry.impl.JcrPackageRegistry.DEFAULT_PACKAGE_ROOT_PATH;
+import static org.apache.jackrabbit.vault.packaging.registry.impl.JcrPackageRegistry.DEFAULT_PACKAGE_ROOT_PATH_PREFIX;
+
 /**
  * Implements the package manager
  */

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/PackageManagerMBeanImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/PackageManagerMBeanImpl.java?rev=1816018&r1=1816017&r2=1816018&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/PackageManagerMBeanImpl.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/PackageManagerMBeanImpl.java Wed Nov 22 09:30:11 2017
@@ -105,7 +105,7 @@ public class PackageManagerMBeanImpl ext
 
     @Override
     protected String getDescription(MBeanAttributeInfo info) {
-        if (info.getName().equals("Packages")) {
+        if ("Packages".equals(info.getName())) {
             return "Available Packages";
         }
         return super.getDescription(info);
@@ -122,7 +122,8 @@ public class PackageManagerMBeanImpl ext
             Session session = null;
             try {
                 session = repository.loginAdministrative(null);
-                JcrPackageManager pkgMgr = new JcrPackageManagerImpl(session);
+                // todo: find a way to use the sling packaging service instead
+                JcrPackageManager pkgMgr = new JcrPackageManagerImpl(session, new String[0]);
                 for (JcrPackage pkg: pkgMgr.listPackages()) {
                     try {
                         Object[] values = {

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/PackagingImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/PackagingImpl.java?rev=1816018&r1=1816017&r2=1816018&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/PackagingImpl.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/PackagingImpl.java Wed Nov 22 09:30:11 2017
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.vault.packaging.impl;
 
+import java.util.Arrays;
+
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
@@ -26,8 +28,14 @@ import org.apache.jackrabbit.vault.packa
 import org.apache.jackrabbit.vault.packaging.PackageManager;
 import org.apache.jackrabbit.vault.packaging.Packaging;
 import org.apache.jackrabbit.vault.packaging.events.impl.PackageEventDispatcher;
+import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * {@code PackagingImpl}...
@@ -37,8 +45,14 @@ import org.osgi.service.component.annota
         immediate = true,
         property = {"service.vendor=The Apache Software Foundation"}
 )
+@Designate(ocd = PackagingImpl.Config.class)
 public class PackagingImpl implements Packaging {
 
+    /**
+     * default logger
+     */
+    private static final Logger log = LoggerFactory.getLogger(PackagingImpl.class);
+
     @Reference
     private PackageEventDispatcher eventDispatcher;
 
@@ -47,10 +61,30 @@ public class PackagingImpl implements Pa
      */
     private final PackageManagerImpl pkgManager = new PackageManagerImpl();
 
+    private String[] packageRoots = new String[0];
+
     public PackagingImpl() {
         pkgManager.setDispatcher(eventDispatcher);
     }
 
+    @ObjectClassDefinition(
+            name = "Apache Jackrabbit Packaging Service"
+    )
+    @interface Config {
+
+        /**
+         * Defines the package roots of the package manager
+         */
+        @AttributeDefinition
+        String[] packageRoots() default {"/etc/packages"};
+    }
+
+    @Activate
+    private void activate(Config config) {
+        this.packageRoots = config.packageRoots();
+        log.info("Jackrabbit Filevault Packaging initialized with roots {}", Arrays.toString(packageRoots));
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -62,7 +96,7 @@ public class PackagingImpl implements Pa
      * {@inheritDoc}
      */
     public JcrPackageManager getPackageManager(Session session) {
-        JcrPackageManagerImpl mgr = new JcrPackageManagerImpl(session);
+        JcrPackageManagerImpl mgr = new JcrPackageManagerImpl(session, packageRoots);
         mgr.setDispatcher(eventDispatcher);
         return mgr;
     }

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/SubPackageExportProcessor.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/SubPackageExportProcessor.java?rev=1816018&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/SubPackageExportProcessor.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/SubPackageExportProcessor.java Wed Nov 22 09:30:11 2017
@@ -0,0 +1,160 @@
+/*
+ * 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.impl;
+
+import java.net.URISyntaxException;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.vault.fs.Mounter;
+import org.apache.jackrabbit.vault.fs.api.PathFilterSet;
+import org.apache.jackrabbit.vault.fs.api.PathMapping;
+import org.apache.jackrabbit.vault.fs.api.RepositoryAddress;
+import org.apache.jackrabbit.vault.fs.api.SimplePathMapping;
+import org.apache.jackrabbit.vault.fs.api.VaultFile;
+import org.apache.jackrabbit.vault.fs.api.VaultFileSystem;
+import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
+import org.apache.jackrabbit.vault.fs.config.DefaultWorkspaceFilter;
+import org.apache.jackrabbit.vault.fs.io.AbstractExporter;
+import org.apache.jackrabbit.vault.packaging.ExportPostProcessor;
+import org.apache.jackrabbit.vault.packaging.JcrPackage;
+import org.apache.jackrabbit.vault.packaging.PackageId;
+import org.apache.jackrabbit.vault.util.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.jackrabbit.vault.packaging.registry.impl.JcrPackageRegistry.DEFAULT_PACKAGE_ROOT_PATH;
+
+/**
+ * Helper class to handle sub-package exporting for non /etc/package package roots
+ */
+public class SubPackageExportProcessor implements ExportPostProcessor {
+
+    /**
+     * default logger
+     */
+    private static final Logger log = LoggerFactory.getLogger(SubPackageExportProcessor.class);
+
+    private JcrPackageManagerImpl mgr;
+
+    private final Session session;
+
+    private final LinkedHashMap<PackageId, String> subPackages = new LinkedHashMap<>();
+
+    public SubPackageExportProcessor(JcrPackageManagerImpl jcrPackageManager, Session session) {
+        this.mgr = jcrPackageManager;
+        this.session = session;
+    }
+
+    public void process(AbstractExporter exporter) {
+        try {
+            for (Map.Entry<PackageId, String> pkg : subPackages.entrySet()) {
+                String nodePath = pkg.getValue();
+                // skip the ones already below /etc/packages
+                if (Text.isDescendantOrEqual(DEFAULT_PACKAGE_ROOT_PATH, nodePath)) {
+                    continue;
+                }
+                String etcPath = DEFAULT_PACKAGE_ROOT_PATH + mgr.getRegistry().getRelativeInstallationPath(pkg.getKey()) + ".zip";
+                etcPath = Text.getRelativeParent(etcPath, 1);
+
+                // define a workspace filter for the package at the real location
+                DefaultWorkspaceFilter filter = new DefaultWorkspaceFilter();
+                filter.add(new PathFilterSet(nodePath));
+
+                // mount the repository at the group node level
+                RepositoryAddress addr;
+                try {
+                    addr = new RepositoryAddress(Text.escapePath("/" + session.getWorkspace().getName() + Text.getRelativeParent(nodePath, 1)));
+                } catch (URISyntaxException e) {
+                    throw new IllegalArgumentException(e);
+                }
+                VaultFileSystem jcrfs = Mounter.mount(null, filter, addr, etcPath, session);
+
+                // perform the export of the first level here, so that we can exclude the .content.xml of the group node
+                for (VaultFile vaultFile : jcrfs.getRoot().getChildren()) {
+                    String path = "jcr_root/" + vaultFile.getName();
+                    if (vaultFile.isDirectory()) {
+                        exporter.createDirectory(vaultFile, path);
+                        exporter.export(vaultFile, path);
+                    } else {
+                        // edge case - we don't export the .content.xml of the group node
+                        if (!path.endsWith("/.content.xml")) {
+                            exporter.writeFile(vaultFile, path);
+                        }
+                    }
+                }
+                jcrfs.unmount();
+            }
+        } catch (Exception e) {
+            log.error("Error during post processing", e);
+        }
+    }
+
+    public WorkspaceFilter prepare(final WorkspaceFilter originalFilter) throws RepositoryException {
+        for (JcrPackage pkg: mgr.listPackages(originalFilter)) {
+            if (pkg.isValid() && pkg.getSize() > 0) {
+                subPackages.put(pkg.getDefinition().getId(), pkg.getNode().getPath());
+            }
+        }
+        // now also get the packages from the primary root
+        WorkspaceFilter filter = originalFilter.translate(new SimplePathMapping(DEFAULT_PACKAGE_ROOT_PATH, mgr.getRegistry().getPackRootPaths()[0]));
+        for (JcrPackage pkg: mgr.listPackages(filter)) {
+            if (pkg.isValid() && pkg.getSize() > 0) {
+                subPackages.put(pkg.getDefinition().getId(), pkg.getNode().getPath());
+            }
+        }
+        if (subPackages.size() > 0) {
+            // now remove the filters with the sub-package information and create distinct ones for the sub packages
+            DefaultWorkspaceFilter newFilter = (DefaultWorkspaceFilter) filter.translate(PathMapping.IDENTITY);
+            Iterator<PathFilterSet> iter = newFilter.getFilterSets().iterator();
+            while (iter.hasNext()) {
+                PathFilterSet set = iter.next();
+                for (String root : mgr.getRegistry().getPackRootPaths()) {
+                    if (Text.isDescendantOrEqual(root, set.getRoot())) {
+                        iter.remove();
+                        break;
+                    }
+                }
+            }
+            iter = newFilter.getPropertyFilterSets().iterator();
+            while (iter.hasNext()) {
+                PathFilterSet set = iter.next();
+                for (String root : mgr.getRegistry().getPackRootPaths()) {
+                    if (Text.isDescendantOrEqual(root, set.getRoot())) {
+                        iter.remove();
+                        break;
+                    }
+                }
+            }
+
+            // re-add all the packages in /etc/packages
+            for (Map.Entry<PackageId, String> pkg : subPackages.entrySet()) {
+                String path = DEFAULT_PACKAGE_ROOT_PATH + mgr.getRegistry().getRelativeInstallationPath(pkg.getKey()) + ".zip";
+                newFilter.add(new PathFilterSet(path));
+            }
+
+            return newFilter;
+        }
+
+        return null;
+    }
+}

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/ZipVaultPackage.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/ZipVaultPackage.java?rev=1816018&r1=1816017&r2=1816018&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/ZipVaultPackage.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/ZipVaultPackage.java Wed Nov 22 09:30:11 2017
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.vault.pack
 
 import java.io.File;
 import java.io.IOException;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Properties;
 import java.util.regex.PatternSyntaxException;

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/JcrPackageRegistry.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/JcrPackageRegistry.java?rev=1816018&r1=1816017&r2=1816018&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/JcrPackageRegistry.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/JcrPackageRegistry.java Wed Nov 22 09:30:11 2017
@@ -21,6 +21,7 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Collections;
 import java.util.LinkedList;
@@ -37,9 +38,11 @@ import javax.jcr.Node;
 import javax.jcr.NodeIterator;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
 
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.commons.JcrUtils;
 import org.apache.jackrabbit.vault.fs.config.MetaInf;
 import org.apache.jackrabbit.vault.fs.io.MemoryArchive;
 import org.apache.jackrabbit.vault.fs.spi.CNDReader;
@@ -87,11 +90,14 @@ public class JcrPackageRegistry implemen
     private static final String DEFAULT_NODETYPES = "nodetypes.cnd";
 
     /**
-     * root path for packages
+     * default root path for packages
      */
-    public static final String PACKAGE_ROOT_PATH = "/etc/packages";
+    public static final String DEFAULT_PACKAGE_ROOT_PATH = "/etc/packages";
 
-    public static final String PACKAGE_ROOT_PATH_PREFIX = "/etc/packages/";
+    /**
+     * default root path prefix for packages
+     */
+    public static final String DEFAULT_PACKAGE_ROOT_PATH_PREFIX = DEFAULT_PACKAGE_ROOT_PATH + "/";
 
     /**
      * suggested folder types
@@ -107,24 +113,52 @@ public class JcrPackageRegistry implemen
     private PackageEventDispatcher dispatcher;
 
     /**
-     * package root (/etc/packages)
+     * package root nodes
+     */
+    private final Node[] packRoots;
+
+    /**
+     * the package root paths.
+     */
+    private final String[] packRootPaths;
+
+    /**
+     * the package root prefix of the primary root path.
      */
-    private Node packRoot;
+    private final String primaryPackRootPathPrefix;
+
 
-    public JcrPackageRegistry(Session session) {
+    /**
+     * Creates a new JcrPackageRegistry based on the given session.
+     * @param session the JCR session that is used to access the repository.
+     * @param roots the root paths to store the packages.
+     */
+    public JcrPackageRegistry(@Nonnull Session session, @Nullable String ... roots) {
         this.session = session;
+        if (roots == null || roots.length == 0) {
+            packRootPaths = new String[]{DEFAULT_PACKAGE_ROOT_PATH};
+        } else {
+            packRootPaths = roots;
+        }
+        packRoots = new Node[packRootPaths.length];
+        primaryPackRootPathPrefix = packRootPaths[0] + "/";
         initNodeTypes();
     }
 
-    @Nullable
-    PackageEventDispatcher getDispatcher() {
-        return dispatcher;
-    }
-
+    /**
+     * Sets the event dispatcher
+     * @param dispatcher the dispatcher.
+     */
     public void setDispatcher(@Nullable PackageEventDispatcher dispatcher) {
         this.dispatcher = dispatcher;
     }
 
+    /**
+     * Dispatches a package event using the configured dispatcher.
+     * @param type event type
+     * @param id package id
+     * @param related related packages
+     */
     public void dispatch(@Nonnull PackageEvent.Type type, @Nonnull PackageId id, @Nullable PackageId[] related) {
         if (dispatcher == null) {
             return;
@@ -160,37 +194,57 @@ public class JcrPackageRegistry implemen
     }
 
     /**
-     * {@inheritDoc}
+     * Returns the package root paths this registry is created with.
+     * @return the package root paths.
      */
-    public Node getPackageRoot(boolean noCreate) throws RepositoryException {
-        if (packRoot == null) {
-            if (session.nodeExists(PACKAGE_ROOT_PATH)) {
-                packRoot = session.getNode(PACKAGE_ROOT_PATH);
-            } else if (noCreate) {
-                return null;
-            } else {
-                // assert that the session has no pending changes
+    @Nonnull
+    public String[] getPackRootPaths() {
+        return packRootPaths;
+    }
+
+    /**
+     * Returns the primary package root. If the root does not exist yet and {@code autoCreate} is {@code true} it will
+     * be created.
+     *
+     * @param autoCreate if {@code true} the roots are created if missing.
+     * @return the the package root or {@code null}
+     * @throws RepositoryException if an error occurs.
+     */
+    @Nullable
+    public Node getPrimaryPackageRoot(boolean autoCreate) throws RepositoryException {
+        if (packRoots[0] == null) {
+            if (session.nodeExists(packRootPaths[0])) {
+                packRoots[0] = session.getNode(packRootPaths[0]);
+            } else if (autoCreate) {
                 if (session.hasPendingChanges()) {
                     throw new RepositoryException("Unwilling to create package root folder while session has transient changes.");
                 }
-                // try to create the missing intermediate nodes
-                String etcPath = Text.getRelativeParent(PACKAGE_ROOT_PATH, 1);
-                Node etc;
-                if (session.nodeExists(etcPath)) {
-                    etc = session.getNode(etcPath);
-                } else {
-                    etc = session.getRootNode().addNode(Text.getName(etcPath), JcrConstants.NT_FOLDER);
-                }
-                Node pack = etc.addNode(Text.getName(PACKAGE_ROOT_PATH), JcrConstants.NT_FOLDER);
-                try {
-                    session.save();
-                } finally {
-                    session.refresh(false);
+                packRoots[0] = JcrUtils.getOrCreateByPath(packRootPaths[0], NodeType.NT_FOLDER, NodeType.NT_FOLDER, session, true);
+            }
+        }
+        return packRoots[0];
+    }
+
+    /**
+     * Returns the list of package roots that currently exist in no particular order.
+     *
+     * @return the list of package roots.
+     * @throws RepositoryException if an error occurs.
+     */
+    @Nonnull
+    public List<Node> getPackageRoots() throws RepositoryException {
+        List<Node> roots = new ArrayList<>(packRootPaths.length);
+        for (int i=0; i<packRootPaths.length; i++) {
+            if (packRoots[i] == null) {
+                if (session.nodeExists(packRootPaths[i])) {
+                    packRoots[i] = session.getNode(packRootPaths[i]);
                 }
-                packRoot = pack;
+            }
+            if (packRoots[i] != null) {
+                roots.add(packRoots[i]);
             }
         }
-        return packRoot;
+        return roots;
     }
 
     @Nullable
@@ -215,11 +269,14 @@ public class JcrPackageRegistry implemen
 
     @Nullable
     private Node getPackageNode(@Nonnull PackageId id) throws RepositoryException {
-        String path = getInstallationPath(id);
-        String[] exts = new String[]{"", ".zip", ".jar"};
-        for (String ext: exts) {
-            if (session.nodeExists(path + ext)) {
-                return session.getNode(path + ext);
+        String relPath = getRelativeInstallationPath(id);
+        for (String pfx: packRootPaths) {
+            String path = pfx + relPath;
+            String[] exts = new String[]{"", ".zip", ".jar"};
+            for (String ext: exts) {
+                if (session.nodeExists(path + ext)) {
+                    return session.getNode(path + ext);
+                }
             }
         }
         return null;
@@ -247,27 +304,28 @@ public class JcrPackageRegistry implemen
     @Override
     public PackageId resolve(Dependency dependency, boolean onlyInstalled) throws IOException {
         try {
-            Node root = getPackageRoot(false);
-            if (!root.hasNode(dependency.getGroup())) {
-                return null;
-            }
-            Node groupNode = root.getNode(dependency.getGroup());
-            NodeIterator iter = groupNode.getNodes();
             PackageId bestId = null;
-            while (iter.hasNext()) {
-                Node child = iter.nextNode();
-                if (".snapshot".equals(child.getName())) {
+            for (Node root: getPackageRoots()) {
+                if (!root.hasNode(dependency.getGroup())) {
                     continue;
                 }
-                try (JcrPackageImpl pack = new JcrPackageImpl(this, child)) {
-                    if (pack.isValid()) {
-                        if (onlyInstalled && !pack.isInstalled()) {
-                            continue;
-                        }
-                        PackageId id = pack.getDefinition().getId();
-                        if (dependency.matches(id)) {
-                            if (bestId == null || id.getVersion().compareTo(bestId.getVersion()) > 0) {
-                                bestId = id;
+                Node groupNode = root.getNode(dependency.getGroup());
+                NodeIterator iter = groupNode.getNodes();
+                while (iter.hasNext()) {
+                    Node child = iter.nextNode();
+                    if (".snapshot".equals(child.getName())) {
+                        continue;
+                    }
+                    try (JcrPackageImpl pack = new JcrPackageImpl(this, child)) {
+                        if (pack.isValid()) {
+                            if (onlyInstalled && !pack.isInstalled()) {
+                                continue;
+                            }
+                            PackageId id = pack.getDefinition().getId();
+                            if (dependency.matches(id)) {
+                                if (bestId == null || id.getVersion().compareTo(bestId.getVersion()) > 0) {
+                                    bestId = id;
+                                }
                             }
                         }
                     }
@@ -711,12 +769,10 @@ public class JcrPackageRegistry implemen
     @Override
     public Set<PackageId> packages() throws IOException {
         try {
-            Node pRoot = getPackageRoot(true);
-            if (pRoot == null) {
-                return Collections.emptySet();
-            }
             Set<PackageId> packages = new TreeSet<PackageId>();
-            listPackages(pRoot, packages);
+            for (Node pRoot: getPackageRoots()) {
+                listPackages(pRoot, packages);
+            }
             return packages;
         } catch (RepositoryException e) {
             throw new IOException(e);
@@ -753,14 +809,25 @@ public class JcrPackageRegistry implemen
     }
 
     /**
-     * Returns the path of this package. please note that since 2.3 this also
+     * Returns the primary path of this package. please note that since 2.3 this also
      * includes the version, but never the extension (.zip).
      *
      * @return the path of this package
      * @since 2.2
      */
-    public static String getInstallationPath(PackageId id) {
-        StringBuilder b = new StringBuilder(PACKAGE_ROOT_PATH_PREFIX);
+    public String getInstallationPath(PackageId id) {
+        return packRootPaths[0] + getRelativeInstallationPath(id);
+    }
+
+    /**
+     * Returns the relative path of this package. please note that since 2.3 this also
+     * includes the version, but never the extension (.zip).
+     *
+     * @return the relative path of this package
+     * @since 2.2
+     */
+    public String getRelativeInstallationPath(PackageId id) {
+        StringBuilder b = new StringBuilder("/");
         if (id.getGroup().length() > 0) {
             b.append(id.getGroup());
             b.append("/");

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImplTest.java?rev=1816018&r1=1816017&r2=1816018&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImplTest.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImplTest.java Wed Nov 22 09:30:11 2017
@@ -16,14 +16,18 @@
  */
 package org.apache.jackrabbit.vault.packaging.impl;
 
+import java.io.IOException;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Set;
 
 import javax.jcr.AccessDeniedException;
 import javax.jcr.GuestCredentials;
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
+import javax.jcr.PathNotFoundException;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.security.AccessControlEntry;
@@ -31,6 +35,10 @@ import javax.jcr.security.AccessControlM
 
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
 import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.vault.packaging.JcrPackage;
+import org.apache.jackrabbit.vault.packaging.JcrPackageManager;
+import org.apache.jackrabbit.vault.packaging.PackageException;
+import org.apache.jackrabbit.vault.packaging.PackageId;
 import org.apache.jackrabbit.vault.packaging.integration.IntegrationTestBase;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -57,7 +65,7 @@ public class JcrPackageManagerImplTest e
         Session session = mock(Session.class);
         when(session.nodeExists(anyString())).thenReturn(false);
         when(session.getWorkspace()).thenReturn(admin.getWorkspace());
-        JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(session);
+        JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(session, new String[0]);
         String path = "/etc/packages";
         try {
             jcrPackageManager.mkdir(path, true);
@@ -73,7 +81,7 @@ public class JcrPackageManagerImplTest e
     @Ignore("unstable results in maven")
     public void testMkDirWithAnonymousSession() throws Exception {
         Session session = repository.login(new GuestCredentials());
-        JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(session);
+        JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(session, new String[0]);
         jcrPackageManager.mkdir("/something/that/is/not/going/to/be/found/anywhere/in/this/repository/even/if/searching/in/very/long/paths/like/this", false);
         jcrPackageManager.mkdir("/something/that/is/not/going/to/be/found/anywhere/in/this/repository/even/if/searching/in/very/long/paths/like/this", false);
         jcrPackageManager.mkdir("/something/that/is/not/going/to/be/found/anywhere/in/this/repository/even/if/searching/in/very/long/paths/like/this", false);
@@ -81,7 +89,7 @@ public class JcrPackageManagerImplTest e
 
     @Test
     public void mkdDirStressTest() throws Exception {
-        JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(admin);
+        JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(admin, new String[0]);
         String path = admin.getRootNode().getPath();
         while (path != null) {
             jcrPackageManager.mkdir(path, true);
@@ -92,14 +100,14 @@ public class JcrPackageManagerImplTest e
 
     @Test
     public void testGetPackageRootNoCreate() throws Exception {
-        JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(admin);
+        JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(admin, new String[0]);
 
         assertNull(jcrPackageManager.getPackageRoot(true));
     }
 
     @Test
     public void testGetPackageRootWithCreate() throws Exception {
-        JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(admin);
+        JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(admin, new String[0]);
 
         Node packageNode = jcrPackageManager.getPackageRoot(false);
         assertEquals("/etc/packages", packageNode.getPath());
@@ -107,16 +115,24 @@ public class JcrPackageManagerImplTest e
 
     @Test
     public void testGetPackageRootTwice() throws Exception {
-        JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(admin);
+        JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(admin, new String[0]);
         Node packageNode = jcrPackageManager.getPackageRoot(false);
         assertSame(packageNode, jcrPackageManager.getPackageRoot());
     }
 
     @Test
+    public void testAlternativePackageRootCreatesOnlyOneNode() throws RepositoryException {
+        JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(admin, new String[]{"/var/packages", "/etc/packages"});
+        Node packageNode = jcrPackageManager.getPackageRoot(false);
+        assertEquals("/var/packages", packageNode.getPath());
+        assertNodeMissing("/etc/packages");
+    }
+
+    @Test
     public void testGetPackageRootWithAdminPendingChanges() throws Exception {
         admin.getRootNode().addNode("testNode");
 
-        JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(admin);
+        JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(admin, new String[0]);
         try {
             jcrPackageManager.getPackageRoot(false);
             fail("transient modifications must fail the package root creation.");
@@ -127,7 +143,7 @@ public class JcrPackageManagerImplTest e
 
     @Test
     public void testGetPackageRootNoRootAccess() throws Exception {
-        Node packageRoot = new JcrPackageManagerImpl(admin).getPackageRoot();
+        Node packageRoot = packMgr.getPackageRoot();
 
         // TODO: maybe rather change the setup of the test-base to not assume that everyone has full read-access
         AccessControlManager acMgr = admin.getAccessControlManager();
@@ -145,7 +161,7 @@ public class JcrPackageManagerImplTest e
             assertFalse(anonymous.nodeExists("/etc"));
             assertTrue(anonymous.nodeExists("/etc/packages"));
 
-            JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(anonymous);
+            JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(anonymous, new String[0]);
             jcrPackageManager.getPackageRoot(false);
         } finally {
             anonymous.logout();
@@ -168,13 +184,13 @@ public class JcrPackageManagerImplTest e
 
         Session anonymous = repository.login(new GuestCredentials());
         try {
-            JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(anonymous);
+            JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(anonymous, new String[0]);
             assertNull(jcrPackageManager.getPackageRoot(true));
 
             try {
                 jcrPackageManager.getPackageRoot(false);
                 fail();
-            } catch (AccessDeniedException e) {
+            } catch (AccessDeniedException | PathNotFoundException e) {
                 // success
             }
         }  finally {
@@ -182,6 +198,94 @@ public class JcrPackageManagerImplTest e
         }
     }
 
+    /**
+     * test package list
+     */
+    @Test
+    public void testListPackages() throws IOException, PackageException, RepositoryException {
+        assertTrue("initially the packages set is empty", packMgr.listPackages().isEmpty());
+        packMgr.upload(getStream("../integration/testpackages/tmp.zip"), false);
+        assertEquals("package list contains 1 element", 1, packMgr.listPackages().size());
+        JcrPackage pkg = packMgr.listPackages().get(0);
+        assertEquals("contains new package", TMP_PACKAGE_ID, pkg.getDefinition().getId());
+    }
+
+    /**
+     * test package list
+     */
+    @Test
+    public void testListPackagesWithGroup() throws IOException, PackageException, RepositoryException {
+        packMgr.upload(getStream("../integration/testpackages/tmp.zip"), false);
+        packMgr.create("foo", "test-package");
+        assertEquals("package list contains 2 elements", 2, packMgr.listPackages().size());
+
+        JcrPackage pkg = packMgr.listPackages("my_packages", false).get(0);
+        assertEquals("contains new package", TMP_PACKAGE_ID, pkg.getDefinition().getId());
+
+        pkg = packMgr.listPackages("foo", false).get(0);
+        assertEquals("contains new package", "foo:test-package", pkg.getDefinition().getId().toString());
+
+        // don't report the not-built one
+        assertEquals("package list contains 2 elements", 0, packMgr.listPackages("foo", true).size());
+    }
+
+    /**
+     * test package list with multiple roots
+     */
+    @Test
+    public void testListPackagesMultiRoot() throws IOException, PackageException, RepositoryException {
+        assertTrue("initially the packages set is empty", packMgr.listPackages().isEmpty());
+        packMgr.upload(getStream("../integration/" + TEST_PACKAGE_A_10), false);
+        packMgr.upload(getStream("../integration/" + TEST_PACKAGE_B_10), false);
+        assertEquals("package list contains 2 elements", 2, packMgr.listPackages().size());
+
+        JcrPackageManager multiRootMgr = new JcrPackageManagerImpl(admin, new String[]{"/var/packages" , "/etc/packages"});
+        assertEquals("package list contains 2 elements", 2, multiRootMgr.listPackages().size());
+
+        // install 3rd package in /var
+        multiRootMgr.upload(getStream("../integration/" + TEST_PACKAGE_C_10), false);
+        List<JcrPackage> pkgs = multiRootMgr.listPackages();
+        assertEquals("packages contains 3 elements", 3, pkgs.size());
+        Set<PackageId> ids = new HashSet<PackageId>();
+        for (JcrPackage p: pkgs) {
+            ids.add(p.getDefinition().getId());
+        }
+
+        assertTrue("contains new packages", ids.contains(TEST_PACKAGE_A_10_ID));
+        assertTrue("contains new packages", ids.contains(TEST_PACKAGE_B_10_ID));
+        assertTrue("contains new packages", ids.contains(TEST_PACKAGE_C_10_ID));
+    }
+
+    /**
+     * test package list with multiple roots
+     */
+    @Test
+    public void testListPackagesMultiRootAndGroup() throws IOException, PackageException, RepositoryException {
+        assertTrue("initially the packages set is empty", packMgr.listPackages().isEmpty());
+        packMgr.upload(getStream("../integration/" + TEST_PACKAGE_A_10), false);
+        packMgr.upload(getStream("../integration/" + TEST_PACKAGE_B_10), false);
+        packMgr.create("foo", "test-package");
+        assertEquals("package list contains 3 elements", 3, packMgr.listPackages().size());
+
+        JcrPackageManager multiRootMgr = new JcrPackageManagerImpl(admin, new String[]{"/var/packages" , "/etc/packages"});
+        assertEquals("package list contains 3 elements", 3, multiRootMgr.listPackages().size());
+
+        // install 3rd package in /var
+        multiRootMgr.upload(getStream("../integration/" + TEST_PACKAGE_C_10), false);
+        multiRootMgr.create("foo", "var-test-package");
+
+        List<JcrPackage> pkgs = multiRootMgr.listPackages("foo", false);
+        assertEquals("packages contains 2 elements", 2, pkgs.size());
+        Set<String> ids = new HashSet<String>();
+        for (JcrPackage p: pkgs) {
+            ids.add(p.getDefinition().getId().toString());
+        }
+
+        assertTrue("contains new packages", ids.contains("foo:test-package"));
+        assertTrue("contains new packages", ids.contains("foo:var-test-package"));
+    }
+
+
     private String getNextPath(String path) throws RepositoryException {
         Node currentNode = admin.getNode(path);
         if (currentNode.hasNodes()) {

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/ImportTests.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/ImportTests.java?rev=1816018&r1=1816017&r2=1816018&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/ImportTests.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/ImportTests.java Wed Nov 22 09:30:11 2017
@@ -41,6 +41,7 @@ import org.apache.jackrabbit.vault.fs.io
 import org.apache.jackrabbit.vault.fs.io.JcrArchive;
 import org.apache.jackrabbit.vault.fs.io.ZipArchive;
 import org.apache.jackrabbit.vault.packaging.PackageException;
+import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -276,6 +277,8 @@ public class ImportTests extends Integra
 
     @Test
     public void testImportWithoutRootAccess() throws IOException, RepositoryException, ConfigurationException {
+        Assume.assumeTrue(!isOak());
+
         // Create test user
         UserManager userManager = ((JackrabbitSession)admin).getUserManager();
         String userId = "user1";
@@ -308,6 +311,8 @@ public class ImportTests extends Integra
 
     @Test
     public void testImportWithoutRootAndTmpAccess() throws IOException, RepositoryException, ConfigurationException {
+        Assume.assumeTrue(!isOak());
+
         // Create test user
         UserManager userManager = ((JackrabbitSession)admin).getUserManager();
         String userId = "user1";

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/IntegrationTestBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/IntegrationTestBase.java?rev=1816018&r1=1816017&r2=1816018&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/IntegrationTestBase.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/IntegrationTestBase.java Wed Nov 22 09:30:11 2017
@@ -123,6 +123,36 @@ public class IntegrationTestBase  {
     private static final File DIR_DATA_STORE = new File(REPO_HOME + "/datastore");
     private static final File DIR_BLOB_STORE = new File(REPO_HOME + "/blobstore");
 
+    public static final PackageId TMP_PACKAGE_ID = new PackageId("my_packages", "tmp", "");
+
+    public static final PackageId TMP_SNAPSHOT_PACKAGE_ID = PackageId.fromString("my_packages/.snapshot:tmp");
+
+    public static final PackageId TEST_PACKAGE_A_10_ID = new PackageId("my_packages", "test_a", "1.0");
+
+    public static final PackageId TEST_PACKAGE_B_10_ID = new PackageId("my_packages", "test_b", "1.0");
+
+    public static final PackageId TEST_PACKAGE_C_10_ID = new PackageId("my_packages", "test_c", "1.0");
+
+    public static final PackageId PACKAGE_ID_SUB_A = PackageId.fromString("my_packages:sub_a");
+
+    public static final PackageId PACKAGE_ID_SUB_B = PackageId.fromString("my_packages:sub_b");
+
+    /**
+     * Test package A-1.0. Depends on B and C-1.X
+     */
+    public static String TEST_PACKAGE_A_10 = "testpackages/test_a-1.0.zip";
+
+    /**
+     * Test package B-1.0. Depends on C
+     */
+    public static String TEST_PACKAGE_B_10 = "testpackages/test_b-1.0.zip";
+
+    /**
+     * Test package C-1.0
+     */
+    public static String TEST_PACKAGE_C_10 = "testpackages/test_c-1.0.zip";
+
+
     @ClassRule
     public static TemporaryFolder tempFolder = new TemporaryFolder();
 
@@ -223,10 +253,11 @@ public class IntegrationTestBase  {
 
         // ensure not packages or tmp
         clean("/etc");
+        clean("/var");
         clean("/tmp");
         clean("/testroot");
 
-        packMgr = new JcrPackageManagerImpl(admin);
+        packMgr = new JcrPackageManagerImpl(admin, new String[0]);
 
         PackageEventDispatcherImpl dispatcher = new PackageEventDispatcherImpl();
         dispatcher.bindPackageEventListener(new ActivityLog(), Collections.singletonMap("component.id", (Object) "1234"));
@@ -384,6 +415,24 @@ public class IntegrationTestBase  {
         return opts;
     }
 
+    /**
+     * Returns the installation path of the package including the ".zip" extension.
+     * @param id the package id
+     * @return the path
+     */
+    public String getInstallationPath(PackageId id) {
+        // make sure we use the one from the test parameter
+        return packMgr.getRegistry().getInstallationPath(id) + ".zip";
+    }
+
+    public void assertPackageNodeExists(PackageId id) throws RepositoryException {
+        assertNodeExists(getInstallationPath(id));
+    }
+
+    public void assertPackageNodeMissing(PackageId id) throws RepositoryException {
+        assertNodeMissing(getInstallationPath(id));
+    }
+
     public void assertNodeExists(String path) throws RepositoryException {
         assertTrue(path + " should exist", admin.nodeExists(path));
     }

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestArchiveExtraction.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestArchiveExtraction.java?rev=1816018&r1=1816017&r2=1816018&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestArchiveExtraction.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestArchiveExtraction.java Wed Nov 22 09:30:11 2017
@@ -87,11 +87,11 @@ public class TestArchiveExtraction exten
         PackageId[] ids = packMgr.extract(a, opts, true);
         validateArchive(a);
         assertEquals(1, ids.length);
-        assertEquals(new PackageId("my_packages", "tmp", ""), ids[0]);
+        assertEquals(TMP_PACKAGE_ID, ids[0]);
         assertNodeExists("/tmp/foo/bar/tobi");
-        assertNodeExists("/etc/packages/my_packages/tmp.zip");
+        assertPackageNodeExists(TMP_PACKAGE_ID);
         // check if size is 0
-        long size = admin.getProperty("/etc/packages/my_packages/tmp.zip/jcr:content/jcr:data").getLength();
+        long size = admin.getProperty(getInstallationPath(TMP_PACKAGE_ID) + "/jcr:content/jcr:data").getLength();
         assertEquals("package binary size", 0, size);
 
         JcrPackage pack = packMgr.open(ids[0]);
@@ -148,13 +148,13 @@ public class TestArchiveExtraction exten
         assertEquals(new PackageId("my_packages", "subtest", ""), ids[0]);
 
         // check for sub packages
-        assertNodeExists("/etc/packages/my_packages/sub_a.zip");
-        long size = admin.getProperty("/etc/packages/my_packages/sub_a.zip/jcr:content/jcr:data").getLength();
+        assertPackageNodeExists(PACKAGE_ID_SUB_A);
+        long size = admin.getProperty(getInstallationPath(PACKAGE_ID_SUB_A)+ "/jcr:content/jcr:data").getLength();
         assertTrue("sub package must have data", size > 0);
         assertNodeMissing("/tmp/a");
 
-        assertNodeExists("/etc/packages/my_packages/sub_b.zip");
-        size = admin.getProperty("/etc/packages/my_packages/sub_b.zip/jcr:content/jcr:data").getLength();
+        assertPackageNodeExists(PACKAGE_ID_SUB_B);
+        size = admin.getProperty(getInstallationPath(PACKAGE_ID_SUB_B)+ "/jcr:content/jcr:data").getLength();
         assertTrue("sub package must have data", size > 0);
         assertNodeMissing("/tmp/b");
     }
@@ -169,17 +169,17 @@ public class TestArchiveExtraction exten
         assertEquals(3, ids.length);
         Set<PackageId> testSet = new HashSet<>(Arrays.asList(ids));
         assertTrue(testSet.contains(new PackageId("my_packages", "subtest", "")));
-        assertTrue(testSet.contains(new PackageId("my_packages", "sub_a", "")));
-        assertTrue(testSet.contains(new PackageId("my_packages", "sub_b", "")));
+        assertTrue(testSet.contains(PACKAGE_ID_SUB_A));
+        assertTrue(testSet.contains(PACKAGE_ID_SUB_B));
 
         // check for sub packages
-        assertNodeExists("/etc/packages/my_packages/sub_a.zip");
-        long size = admin.getProperty("/etc/packages/my_packages/sub_a.zip/jcr:content/jcr:data").getLength();
+        assertPackageNodeExists(PACKAGE_ID_SUB_A);
+        long size = admin.getProperty(getInstallationPath(PACKAGE_ID_SUB_A)+ "/jcr:content/jcr:data").getLength();
         assertEquals("sub package must no data", 0, size);
         assertNodeExists("/tmp/a");
 
-        assertNodeExists("/etc/packages/my_packages/sub_b.zip");
-        size = admin.getProperty("/etc/packages/my_packages/sub_b.zip/jcr:content/jcr:data").getLength();
+        assertPackageNodeExists(PACKAGE_ID_SUB_B);
+        size = admin.getProperty(getInstallationPath(PACKAGE_ID_SUB_B)+ "/jcr:content/jcr:data").getLength();
         assertEquals("sub package must no data", 0, size);
         assertNodeExists("/tmp/b");
     }

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestNoRootAccessExport.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestNoRootAccessExport.java?rev=1816018&r1=1816017&r2=1816018&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestNoRootAccessExport.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestNoRootAccessExport.java Wed Nov 22 09:30:11 2017
@@ -46,7 +46,7 @@ public class TestNoRootAccessExport exte
     @Ignore("JCRVLT-100")
     public void exportNoRootAccess() throws RepositoryException, IOException, PackageException {
         // setup access control
-        Node packageRoot = new JcrPackageManagerImpl(admin).getPackageRoot();
+        Node packageRoot = new JcrPackageManagerImpl(admin, new String[0]).getPackageRoot();
         AccessControlManager acMgr = admin.getAccessControlManager();
         JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(acMgr, "/");
         acMgr.removePolicy(acl.getPath(), acl);
@@ -54,7 +54,7 @@ public class TestNoRootAccessExport exte
         AccessControlUtils.getAccessControlList(acMgr, packageRoot.getPath());
         AccessControlUtils.allow(packageRoot, org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal.NAME, Privilege.JCR_ALL);
 
-        Node tmpNode = new JcrPackageManagerImpl(admin).getPackageRoot();
+        Node tmpNode = new JcrPackageManagerImpl(admin, new String[0]).getPackageRoot();
         AccessControlUtils.getAccessControlList(acMgr, tmpNode.getPath());
         AccessControlUtils.allow(tmpNode, org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal.NAME, Privilege.JCR_ALL);
 
@@ -69,7 +69,7 @@ public class TestNoRootAccessExport exte
 
         // login as guest an
         Session anonymous = repository.login(new GuestCredentials());
-        JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(anonymous);
+        JcrPackageManagerImpl jcrPackageManager = new JcrPackageManagerImpl(anonymous, new String[0]);
         pack = jcrPackageManager.open(id);
         jcrPackageManager.assemble(pack, null);
     }

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestPackageCreation.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestPackageCreation.java?rev=1816018&r1=1816017&r2=1816018&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestPackageCreation.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestPackageCreation.java Wed Nov 22 09:30:11 2017
@@ -22,6 +22,7 @@ import java.io.IOException;
 import javax.jcr.RepositoryException;
 
 import org.apache.jackrabbit.vault.packaging.PackageException;
+import org.apache.jackrabbit.vault.packaging.PackageId;
 import org.junit.Test;
 
 import static org.junit.Assert.fail;
@@ -43,7 +44,7 @@ public class TestPackageCreation extends
     public void testCreateGroup() throws RepositoryException, IOException, PackageException {
         for (String name: GROUP_NAMES) {
             packMgr.create(name, "bar");
-            assertNodeExists("/etc/packages/" + name + "/bar.zip");
+            assertPackageNodeExists(new PackageId(name, "bar", ""));
         }
     }
 
@@ -51,14 +52,14 @@ public class TestPackageCreation extends
     public void testCreate() throws RepositoryException, IOException, PackageException {
         for (String name: PACKAGE_NAMES) {
             packMgr.create("foo", name);
-            assertNodeExists("/etc/packages/foo/" + name + ".zip");
+            assertPackageNodeExists(new PackageId("foo", name, ""));
         }
     }
 
     @Test
     public void testCreateWithVersion() throws RepositoryException, IOException, PackageException {
         packMgr.create("foo", "bar", "3.1.2");
-        assertNodeExists("/etc/packages/foo/bar-3.1.2.zip");
+        assertPackageNodeExists(new PackageId("foo", "bar", "3.1.2"));
     }
 
     @Test