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/09/29 04:16:58 UTC

svn commit: r1810052 [1/3] - in /jackrabbit/commons/filevault/trunk: parent/ vault-core/ vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/ vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/ vault-core/src/main/java/org/apache/jac...

Author: tripod
Date: Fri Sep 29 04:16:57 2017
New Revision: 1810052

URL: http://svn.apache.org/viewvc?rev=1810052&view=rev
Log:
JCRVLT-172 Introduce Package Persistence Layer

Added:
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/NoSuchPackageException.java
      - copied, changed from r1805059, jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageExistsException.java
      - copied, changed from r1805059, jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/DependencyReport.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/ExecutionPlan.java
      - copied, changed from r1805059, jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/ExecutionPlanBuilder.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/PackageRegistry.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/PackageTask.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/PackageTaskBuilder.java
      - copied, changed from r1805059, jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/RegisteredPackage.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/DependencyReportImpl.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/ExecutionPlanBuilderImpl.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/ExecutionPlanImpl.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/JcrPackageRegistry.java
      - copied, changed from r1805059, 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/registry/impl/JcrRegisteredPackage.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/PackageTaskImpl.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/package-info.java
      - copied, changed from r1805059, jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/package-info.java
    jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestExecutionPlan.java
    jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestPackageRegistry.java
Modified:
    jackrabbit/commons/filevault/trunk/parent/pom.xml
    jackrabbit/commons/filevault/trunk/vault-core/pom.xml
    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/PackageException.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/package-info.java
    jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestArchiveExtraction.java

Modified: jackrabbit/commons/filevault/trunk/parent/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/parent/pom.xml?rev=1810052&r1=1810051&r2=1810052&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/parent/pom.xml (original)
+++ jackrabbit/commons/filevault/trunk/parent/pom.xml Fri Sep 29 04:16:57 2017
@@ -42,6 +42,7 @@
     <properties>
         <jackrabbit.version>2.14.2</jackrabbit.version>
         <oak.version>1.6.1</oak.version>
+        <slf4j.version>1.7.6</slf4j.version>
     </properties>
 
     <!-- ====================================================================== -->
@@ -307,13 +308,13 @@
             <dependency>
                 <groupId>org.slf4j</groupId>
                 <artifactId>slf4j-log4j12</artifactId>
-                <version>1.5.8</version>
+                <version>${slf4j.version}</version>
                 <scope>provided</scope>
             </dependency>
             <dependency>
                 <groupId>org.slf4j</groupId>
                 <artifactId>slf4j-api</artifactId>
-                <version>1.5.8</version>
+                <version>${slf4j.version}</version>
                 <scope>provided</scope>
             </dependency>
             <dependency>

Modified: jackrabbit/commons/filevault/trunk/vault-core/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/pom.xml?rev=1810052&r1=1810051&r2=1810052&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/pom.xml (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/pom.xml Fri Sep 29 04:16:57 2017
@@ -184,7 +184,7 @@
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-simple</artifactId>
-            <version>1.5.8</version>
+            <version>${slf4j.version}</version>
             <scope>test</scope>
         </dependency>
         <dependency>

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=1810052&r1=1810051&r2=1810052&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 Fri Sep 29 04:16:57 2017
@@ -77,6 +77,7 @@ import org.apache.jackrabbit.vault.fs.sp
 import org.apache.jackrabbit.vault.fs.spi.ProgressTracker;
 import org.apache.jackrabbit.vault.fs.spi.ServiceProviderFactory;
 import org.apache.jackrabbit.vault.fs.spi.UserManagement;
+import org.apache.jackrabbit.vault.packaging.registry.impl.JcrPackageRegistry;
 import org.apache.jackrabbit.vault.util.Constants;
 import org.apache.jackrabbit.vault.util.PlatformNameFormat;
 import org.apache.jackrabbit.vault.util.Text;
@@ -84,8 +85,6 @@ import org.apache.jackrabbit.vault.util.
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import static org.apache.jackrabbit.vault.packaging.impl.JcrPackageManagerImpl.PACKAGE_ROOT_PATH_PREFIX;
-
 /**
  * {@code AbstractImporter}
  *
@@ -652,7 +651,7 @@ public class Importer {
                     }
                 }
                 // todo: find better way to detect sub-packages
-                if (repoPath.startsWith(PACKAGE_ROOT_PATH_PREFIX) && (repoPath.endsWith(".jar") || repoPath.endsWith(".zip"))) {
+                if (repoPath.startsWith(JcrPackageRegistry.PACKAGE_ROOT_PATH_PREFIX) && (repoPath.endsWith(".jar") || repoPath.endsWith(".zip"))) {
                     subPackages.add(repoPath);
                 }
 
@@ -679,7 +678,7 @@ public class Importer {
                         serType = SerializationType.GENERIC;
                         type = ArtifactType.FILE;
                     }
-                } else if (ext.equals(".cnd")) {
+                } else if (".cnd".equals(ext)) {
                     if (opts.getCndPattern().matcher(repoPath).matches()) {
                         InputStream in = is.getByteStream();
                         try {
@@ -697,10 +696,10 @@ public class Importer {
                     }
                     ext = "";
                     type = ArtifactType.FILE;
-                } else if (ext.equals(".xcnd")) {
+                } else if (".xcnd".equals(ext)) {
                     serType = SerializationType.CND;
                     repoName = repoBase;
-                } else if (ext.equals(".binary")) {
+                } else if (".binary".equals(ext)) {
                     serType = SerializationType.GENERIC;
                     type = ArtifactType.BINARY;
                     repoName = repoBase;

Copied: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/NoSuchPackageException.java (from r1805059, jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java)
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/NoSuchPackageException.java?p2=jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/NoSuchPackageException.java&p1=jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java&r1=1805059&r2=1810052&rev=1810052&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/NoSuchPackageException.java Fri Sep 29 04:16:57 2017
@@ -17,24 +17,38 @@
 
 package org.apache.jackrabbit.vault.packaging;
 
+import javax.annotation.Nullable;
+
 /**
- * {@code PackageException}...
+ * Exception for errors where a specified package does not exist
  */
-public class PackageException extends Exception {
+public class NoSuchPackageException extends PackageException {
+
+    private PackageId id;
 
-    public PackageException() {
+    public NoSuchPackageException() {
         super();
     }
 
-    public PackageException(String message) {
+    public NoSuchPackageException(String message) {
         super(message);
     }
 
-    public PackageException(String message, Throwable cause) {
+    public NoSuchPackageException(String message, Throwable cause) {
         super(message, cause);
     }
 
-    public PackageException(Throwable cause) {
+    public NoSuchPackageException(Throwable cause) {
         super(cause);
     }
+
+    @Nullable
+    public PackageId getId() {
+        return id;
+    }
+
+    public NoSuchPackageException setId(PackageId id) {
+        this.id = id;
+        return this;
+    }
 }
\ No newline at end of file

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java?rev=1810052&r1=1810051&r2=1810052&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java Fri Sep 29 04:16:57 2017
@@ -18,7 +18,7 @@
 package org.apache.jackrabbit.vault.packaging;
 
 /**
- * {@code PackageException}...
+ * Generic exception for package related operations.
  */
 public class PackageException extends Exception {
 

Copied: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageExistsException.java (from r1805059, jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java)
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageExistsException.java?p2=jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageExistsException.java&p1=jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java&r1=1805059&r2=1810052&rev=1810052&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageExistsException.java Fri Sep 29 04:16:57 2017
@@ -17,24 +17,38 @@
 
 package org.apache.jackrabbit.vault.packaging;
 
+import javax.annotation.Nullable;
+
 /**
- * {@code PackageException}...
+ * Exception thrown if a specified package already exist.
  */
-public class PackageException extends Exception {
+public class PackageExistsException extends PackageException {
+
+    private PackageId id;
 
-    public PackageException() {
+    public PackageExistsException() {
         super();
     }
 
-    public PackageException(String message) {
+    public PackageExistsException(String message) {
         super(message);
     }
 
-    public PackageException(String message, Throwable cause) {
+    public PackageExistsException(String message, Throwable cause) {
         super(message, cause);
     }
 
-    public PackageException(Throwable cause) {
+    public PackageExistsException(Throwable cause) {
         super(cause);
     }
+
+    @Nullable
+    public PackageId getId() {
+        return id;
+    }
+
+    public PackageExistsException setId(PackageId id) {
+        this.id = id;
+        return this;
+    }
 }
\ No newline at end of file

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=1810052&r1=1810051&r2=1810052&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 Fri Sep 29 04:16:57 2017
@@ -878,7 +878,7 @@ public class JcrPackageDefinitionImpl im
      * Returns a new state object that can be used to save modification information.
      * @return a new state object.
      */
-    protected State getState() {
+    public State getState() {
         return new State().load(this);
     }
 
@@ -886,11 +886,11 @@ public class JcrPackageDefinitionImpl im
      * Sets the information stored in the state object back to this definition.
      * @param state the sate
      */
-    protected void setState(State state) {
+    public void setState(State state) {
         state.save(this);
     }
 
-    protected static class State {
+    public static class State {
 
         private final String[] PROPERTY_NAMES = {
                 PN_LAST_UNPACKED,    PN_LAST_UNWRAPPED,    PN_LASTMODIFIED,    PN_LAST_WRAPPED,

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=1810052&r1=1810051&r2=1810052&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 Fri Sep 29 04:16:57 2017
@@ -71,6 +71,9 @@ import org.apache.jackrabbit.vault.packa
 import org.apache.jackrabbit.vault.packaging.VaultPackage;
 import org.apache.jackrabbit.vault.packaging.Version;
 import org.apache.jackrabbit.vault.packaging.events.PackageEvent;
+import org.apache.jackrabbit.vault.packaging.registry.RegisteredPackage;
+import org.apache.jackrabbit.vault.packaging.registry.impl.JcrPackageRegistry;
+import org.apache.jackrabbit.vault.packaging.registry.impl.JcrRegisteredPackage;
 import org.apache.jackrabbit.vault.util.JcrConstants;
 import org.apache.jackrabbit.vault.util.Text;
 import org.slf4j.Logger;
@@ -96,7 +99,7 @@ public class JcrPackageImpl implements J
     /**
      * our package manager
      */
-    private final JcrPackageManagerImpl mgr;
+    private final JcrPackageRegistry mgr;
 
     /**
      * underlying node
@@ -116,12 +119,12 @@ public class JcrPackageImpl implements J
     @Nullable
     private JcrPackageDefinitionImpl def;
 
-    public JcrPackageImpl(@Nonnull JcrPackageManagerImpl mgr, @Nullable Node node) throws RepositoryException {
+    public JcrPackageImpl(@Nonnull JcrPackageRegistry mgr, @Nullable Node node) throws RepositoryException {
         this.mgr = mgr;
         this.node = node;
     }
 
-    protected JcrPackageImpl(@Nonnull JcrPackageManagerImpl mgr, @Nullable Node node, @Nullable ZipVaultPackage pack) throws RepositoryException {
+    public JcrPackageImpl(@Nonnull JcrPackageRegistry mgr, @Nullable Node node, @Nullable ZipVaultPackage pack) throws RepositoryException {
         this.mgr = mgr;
         this.node = node;
         this.pack = pack;
@@ -233,7 +236,7 @@ public class JcrPackageImpl implements J
         PackageId cId = new PackageId(node.getPath());
         // compare installation paths since non-conform version numbers might
         // lead to different pids (bug #35564)
-        if (JcrPackageManagerImpl.getInstallationPath(id).equals(JcrPackageManagerImpl.getInstallationPath(cId))) {
+        if (JcrPackageRegistry.getInstallationPath(id).equals(JcrPackageRegistry.getInstallationPath(cId))) {
             if (autoFix && id.isFromPath()) {
                 // if definition has no id set, fix anyways
                 jDef.setId(cId, autoSave);
@@ -574,7 +577,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(JcrPackageManagerImpl.PACKAGE_ROOT_PATH, root.getRoot())) {
+            if (!Text.isDescendantOrEqual(JcrPackageRegistry.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;
@@ -612,8 +615,15 @@ public class JcrPackageImpl implements J
                 ins = in.getByteStream();
                 JcrPackageImpl subPackage;
                 try {
-                    subPackage = (JcrPackageImpl) mgr.upload(ins, true, true);
-                } catch (RepositoryException e1) {
+                    PackageId subPid = mgr.register(ins, true);
+                    JcrRegisteredPackage subPkg = (JcrRegisteredPackage) mgr.open(subPid);
+                    if (subPkg == null) {
+                        log.error("Package {}: Newly extracted subpackage is gone: {}", pId, subPid);
+                        continue;
+                    } else {
+                        subPackage = (JcrPackageImpl) subPkg.getJcrPackage();
+                    }
+                } catch (IOException e1) {
                     log.error("Package {}: Error while extracting subpackage {}: {}", pId, in.getSystemId());
                     continue;
                 }
@@ -688,8 +698,15 @@ public class JcrPackageImpl implements J
         }
         List<Dependency> unresolved = new LinkedList<Dependency>();
         for (Dependency dep: def.getDependencies()) {
-            if (mgr.resolve(dep, true) == null) {
-                unresolved.add(dep);
+            try {
+                if (mgr.resolve(dep, true) == null) {
+                    unresolved.add(dep);
+                }
+            } catch (IOException e) {
+                if (e.getCause() instanceof RepositoryException) {
+                    throw (RepositoryException) e.getCause();
+                }
+                throw new RepositoryException(e);
             }
         }
         return unresolved.toArray(new Dependency[unresolved.size()]);
@@ -706,9 +723,16 @@ public class JcrPackageImpl implements J
         }
         List<PackageId> resolved = new LinkedList<PackageId>();
         for (Dependency dep: def.getDependencies()) {
-            PackageId id = mgr.resolve(dep, true);
-            if (id != null) {
-                resolved.add(id);
+            try {
+                PackageId id = mgr.resolve(dep, true);
+                if (id != null) {
+                    resolved.add(id);
+                }
+            } catch (IOException e) {
+                if (e.getCause() instanceof RepositoryException) {
+                    throw (RepositoryException) e.getCause();
+                }
+                throw new RepositoryException(e);
             }
         }
         return resolved.toArray(new PackageId[resolved.size()]);
@@ -731,10 +755,10 @@ public class JcrPackageImpl implements J
             if (id == null) {
                 unresolved.add(dep);
             } else {
-                JcrPackageImpl pack = (JcrPackageImpl) mgr.open(id);
-                if (!pack.isInstalled()) {
+                JcrRegisteredPackage pack = (JcrRegisteredPackage) mgr.open(id);
+                if (pack != null && !pack.isInstalled()) {
                     unresolved.add(dep);
-                    uninstalled.add(pack);
+                    uninstalled.add((JcrPackageImpl) pack.getJcrPackage());
                 }
             }
         }
@@ -784,16 +808,19 @@ public class JcrPackageImpl implements J
             throw new DependencyException(msg);
         }
         for (PackageId id: usage) {
-            JcrPackageImpl pack = (JcrPackageImpl) mgr.open(id);
-            if (pack == null || !pack.isInstalled()) {
-                continue;
-            }
-            PackageId packageId = pack.getDefinition().getId();
-            if (processed.contains(packageId)) {
-                // ignore cyclic...
-                continue;
+            try (JcrRegisteredPackage pack = (JcrRegisteredPackage) mgr.open(id)) {
+                if (pack == null || !pack.isInstalled()) {
+                    continue;
+                }
+                PackageId packageId = pack.getId();
+                if (processed.contains(packageId)) {
+                    // ignore cyclic...
+                    continue;
+                }
+
+                //noinspection resource
+                ((JcrPackageImpl) pack.getJcrPackage()).uninstall(processed, opts);
             }
-            pack.uninstall(processed, opts);
         }
     }
 
@@ -834,7 +861,7 @@ public class JcrPackageImpl implements J
         }
         log.debug("Creating snapshot for {}.", id);
         JcrPackageManagerImpl packMgr = new JcrPackageManagerImpl(node.getSession());
-        String path = JcrPackageManagerImpl.getInstallationPath(id);
+        String path = JcrPackageRegistry.getInstallationPath(id);
         String parentPath = Text.getRelativeParent(path, 1);
         Node folder = packMgr.mkdir(parentPath, true);
         JcrPackage snap = mgr.createNew(folder, id, null, true);
@@ -868,7 +895,7 @@ public class JcrPackageImpl implements J
         if (node == null) {
             return null;
         }
-        String path = JcrPackageManagerImpl.getInstallationPath(id);
+        String path = JcrPackageRegistry.getInstallationPath(id);
         if (node.getSession().nodeExists(path)) {
             return node.getSession().getNode(path);
         } else if (node.getSession().nodeExists(path + ".zip")) {

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=1810052&r1=1810051&r2=1810052&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 Fri Sep 29 04:16:57 2017
@@ -17,12 +17,9 @@
 
 package org.apache.jackrabbit.vault.packaging.impl;
 
-import java.io.ByteArrayInputStream;
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.util.Arrays;
 import java.util.Calendar;
@@ -30,13 +27,10 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Properties;
 import java.util.Set;
-import java.util.TreeSet;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
-import javax.jcr.Binary;
 import javax.jcr.ItemExistsException;
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
@@ -44,35 +38,28 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
 import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
 import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener;
 import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
-import org.apache.jackrabbit.vault.fs.config.MetaInf;
 import org.apache.jackrabbit.vault.fs.impl.ArchiveWrapper;
 import org.apache.jackrabbit.vault.fs.impl.SubPackageFilterArchive;
 import org.apache.jackrabbit.vault.fs.io.Archive;
 import org.apache.jackrabbit.vault.fs.io.ImportOptions;
-import org.apache.jackrabbit.vault.fs.io.MemoryArchive;
-import org.apache.jackrabbit.vault.fs.io.ZipArchive;
 import org.apache.jackrabbit.vault.fs.io.ZipStreamArchive;
-import org.apache.jackrabbit.vault.fs.spi.CNDReader;
-import org.apache.jackrabbit.vault.fs.spi.NodeTypeInstaller;
-import org.apache.jackrabbit.vault.fs.spi.ServiceProviderFactory;
 import org.apache.jackrabbit.vault.packaging.Dependency;
 import org.apache.jackrabbit.vault.packaging.ExportOptions;
 import org.apache.jackrabbit.vault.packaging.JcrPackage;
 import org.apache.jackrabbit.vault.packaging.JcrPackageDefinition;
 import org.apache.jackrabbit.vault.packaging.JcrPackageManager;
+import org.apache.jackrabbit.vault.packaging.NoSuchPackageException;
 import org.apache.jackrabbit.vault.packaging.PackageException;
+import org.apache.jackrabbit.vault.packaging.PackageExistsException;
 import org.apache.jackrabbit.vault.packaging.PackageId;
 import org.apache.jackrabbit.vault.packaging.VaultPackage;
-import org.apache.jackrabbit.vault.packaging.Version;
 import org.apache.jackrabbit.vault.packaging.events.PackageEvent;
-import org.apache.jackrabbit.vault.util.InputStreamPump;
+import org.apache.jackrabbit.vault.packaging.events.impl.PackageEventDispatcher;
+import org.apache.jackrabbit.vault.packaging.registry.impl.JcrPackageRegistry;
+import org.apache.jackrabbit.vault.packaging.registry.impl.JcrRegisteredPackage;
 import org.apache.jackrabbit.vault.util.JcrConstants;
-import org.apache.jackrabbit.vault.util.Text;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Extends the {@code PackageManager} by JCR specific methods
@@ -80,44 +67,14 @@ import org.slf4j.LoggerFactory;
 public class JcrPackageManagerImpl extends PackageManagerImpl implements JcrPackageManager {
 
     /**
-     * default logger
-     */
-    private static final Logger log = LoggerFactory.getLogger(JcrPackageManagerImpl.class);
-
-    /**
-     * name of node types resource
-     */
-    private static final String DEFAULT_NODETYPES = "nodetypes.cnd";
-
-    /**
-     * suggested folder types
-     */
-    private final static String[] FOLDER_TYPES = {"sling:Folder", "nt:folder", "nt:unstructured", null};
-
-    /**
-     * root path for packages
-     */
-    final static String PACKAGE_ROOT_PATH = "/etc/packages";
-
-    /**
-     * root path prefix for packages
-     */
-    public final static String PACKAGE_ROOT_PATH_PREFIX = "/etc/packages/";
-
-    /**
      * root path for packages
      */
     public final static String ARCHIVE_PACKAGE_ROOT_PATH = "/jcr_root/etc/packages";
 
     /**
-     * internal session
-     */
-    private final Session session;
-
-    /**
-     * package root (/etc/packages)
+     * internal package persistence
      */
-    private Node packRoot;
+    private final JcrPackageRegistry registry;
 
     /**
      * Creates a new package manager using the given session.
@@ -125,25 +82,41 @@ public class JcrPackageManagerImpl exten
      * @param session repository session
      */
     public JcrPackageManagerImpl(Session session) {
-        this.session = session;
-        initNodeTypes();
+        this(new JcrPackageRegistry(session));
     }
 
+    private JcrPackageManagerImpl(JcrPackageRegistry registry) {
+        this.registry = registry;
+    }
+
+    private RepositoryException unwrapRepositoryException(Exception e) {
+        if (e.getCause() instanceof RepositoryException) {
+            return (RepositoryException) e.getCause();
+        }
+        return new RepositoryException(e);
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public JcrPackage open(PackageId id) throws RepositoryException {
-        String path = getInstallationPath(id);
-        String[] exts = new String[]{"", ".zip", ".jar"};
-        for (String ext: exts) {
-            if (session.nodeExists(path + ext)) {
-                return open(session.getNode(path + ext));
-            }
+        try {
+            //noinspection resource
+            JcrRegisteredPackage pkg = (JcrRegisteredPackage) registry.open(id);
+            return pkg == null ? null : pkg.getJcrPackage();
+        } catch (IOException e) {
+            throw unwrapRepositoryException(e);
         }
-        return null;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public JcrPackage open(Node node) throws RepositoryException {
-        return open(node, false);
+        return registry.open(node, false);
     }
 
     /**
@@ -151,16 +124,7 @@ public class JcrPackageManagerImpl exten
      */
     @Override
     public JcrPackage open(Node node, boolean allowInvalid) throws RepositoryException {
-        JcrPackage pack = new JcrPackageImpl(this, node);
-        if (pack.isValid()) {
-            return pack;
-        } else if (allowInvalid
-                && node.isNodeType(JcrConstants.NT_HIERARCHYNODE)
-                && node.hasProperty(JcrConstants.JCR_CONTENT + "/" + JcrConstants.JCR_DATA)) {
-            return pack;
-        } else {
-            return null;
-        }
+        return registry.open(node, allowInvalid);
     }
 
     /**
@@ -168,32 +132,11 @@ public class JcrPackageManagerImpl exten
      */
     @Override
     public PackageId resolve(Dependency dependency, boolean onlyInstalled) throws RepositoryException {
-        if (!getPackageRoot().hasNode(dependency.getGroup())) {
-            return null;
-        }
-        Node groupNode = getPackageRoot().getNode(dependency.getGroup());
-        NodeIterator iter = groupNode.getNodes();
-        PackageId bestId = null;
-        while (iter.hasNext()) {
-            Node child = iter.nextNode();
-            if (".snapshot".equals(child.getName())) {
-                continue;
-            }
-            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;
-                    }
-                }
-            }
-
+        try {
+            return registry.resolve(dependency, onlyInstalled);
+        } catch (IOException e) {
+            throw unwrapRepositoryException(e);
         }
-        return bestId;
     }
 
     /**
@@ -201,19 +144,11 @@ public class JcrPackageManagerImpl exten
      */
     @Override
     public PackageId[] usage(PackageId id) throws RepositoryException {
-        TreeSet<PackageId> usages = new TreeSet<PackageId>();
-        for (JcrPackage p: listPackages()) {
-            if (!p.isInstalled()) {
-                continue;
-            }
-            for (Dependency dep: p.getDefinition().getDependencies()) {
-                if (dep.matches(id)) {
-                    usages.add(p.getDefinition().getId());
-                    break;
-                }
-            }
+        try {
+            return registry.usage(id);
+        } catch (IOException e) {
+            throw unwrapRepositoryException(e);
         }
-        return usages.toArray(new PackageId[usages.size()]);
     }
 
     /**
@@ -230,85 +165,10 @@ public class JcrPackageManagerImpl exten
     @Override
     public JcrPackage upload(InputStream in, boolean replace, boolean strict)
             throws RepositoryException, IOException {
-
-        MemoryArchive archive = new MemoryArchive(true);
-        InputStreamPump pump = new InputStreamPump(in , archive);
-
-        // this will cause the input stream to be consumed and the memory archive being initialized.
-        Binary bin = session.getValueFactory().createBinary(pump);
-        if (pump.getError() != null) {
-            Exception error = pump.getError();
-            log.error("Error while reading from input stream.", error);
-            bin.dispose();
-            throw new IOException("Error while reading from input stream", error);
-        }
-
-        if (archive.getJcrRoot() == null) {
-            String msg = "Stream is not a content package. Missing 'jcr_root'.";
-            log.error(msg);
-            bin.dispose();
-            throw new IOException(msg);
-        }
-
-        final MetaInf inf = archive.getMetaInf();
-        PackagePropertiesImpl props = new PackagePropertiesImpl() {
-            @Override
-            protected Properties getPropertiesMap() {
-                return inf.getProperties();
-            }
-        };
-        PackageId pid = props.getId();
-
-        // invalidate pid if path is unknown
-        if (pid == null) {
-            bin.dispose();
-            throw new IOException("Package does not contain a path specification or valid package id.");
-        }
-        if (!pid.isValid()) {
-            throw new RepositoryException("Unable to create package. Illegal package name.");
-        }
-
-        // create parent node
-        String path = getInstallationPath(pid) + ".zip";
-        String parentPath = Text.getRelativeParent(path, 1);
-        String name = Text.getName(path);
-        Node parent = mkdir(parentPath, false);
-
-        // remember installation state properties (GRANITE-2018)
-        JcrPackageDefinitionImpl.State state = null;
-        Calendar oldCreatedDate = null;
-
-        if (parent.hasNode(name)) {
-            JcrPackage oldPackage = new JcrPackageImpl(this, parent.getNode(name));
-            JcrPackageDefinitionImpl oldDef = (JcrPackageDefinitionImpl) oldPackage.getDefinition();
-            if (oldDef != null) {
-                state = oldDef.getState();
-                oldCreatedDate = oldDef.getCreated();
-            }
-
-            if (replace) {
-                parent.getNode(name).remove();
-            } else {
-                throw new ItemExistsException("Package already exists: " + path);
-            }
-        }
-        JcrPackage jcrPack = null;
         try {
-            jcrPack = createNew(parent, pid, bin, archive);
-            JcrPackageDefinitionImpl def = (JcrPackageDefinitionImpl) jcrPack.getDefinition();
-            // only transfer the old package state to the new state in case both packages have the same create date
-            if (state != null && oldCreatedDate != null && oldCreatedDate.compareTo(def.getCreated()) == 0) {
-                def.setState(state);
-            }
-            dispatch(PackageEvent.Type.UPLOAD, pid, null);
-            return jcrPack;
-        } finally {
-            bin.dispose();
-            if (jcrPack == null) {
-                session.refresh(false);
-            } else {
-                session.save();
-            }
+            return registry.upload(in, replace);
+        } catch (PackageExistsException e) {
+            throw new ItemExistsException(e.getMessage(), e);
         }
     }
 
@@ -330,8 +190,8 @@ public class JcrPackageManagerImpl exten
         ZipVaultPackage pkg = new ZipVaultPackage(archive, true);
 
         PackageId pid = pkg.getId();
-        JcrPackage jcrPack = upload(pkg, replace, null);
-        jcrPack = new JcrPackageImpl(this, jcrPack.getNode(), pkg);
+        JcrPackage jcrPack = registry.upload(pkg, replace);
+        jcrPack = new JcrPackageImpl(registry, jcrPack.getNode(), pkg);
         jcrPack.extract(options);
 
         Set<PackageId> ids = new HashSet<>();
@@ -340,10 +200,12 @@ public class JcrPackageManagerImpl exten
         if (spfArchive != null) {
             for (Archive.Entry e: spfArchive.getSubPackageEntries()) {
                 InputStream in = spfArchive.openInputStream(e);
-                Archive subArchive = new ZipStreamArchive(in);
-                PackageId[] subIds = extract(subArchive, options, replace);
-                ids.addAll(Arrays.asList(subIds));
-                subArchive.close();
+                if (in != null) {
+                    Archive subArchive = new ZipStreamArchive(in);
+                    PackageId[] subIds = extract(subArchive, options, replace);
+                    ids.addAll(Arrays.asList(subIds));
+                    subArchive.close();
+                }
             }
         }
 
@@ -369,69 +231,10 @@ public class JcrPackageManagerImpl exten
     public JcrPackage upload(File file, boolean isTmpFile, boolean replace, String nameHint, boolean strict)
             throws RepositoryException, IOException {
         ZipVaultPackage pack = new ZipVaultPackage(file, isTmpFile, strict);
-        return upload(pack, replace, nameHint);
-    }
-
-    private JcrPackage upload(ZipVaultPackage pkg, boolean replace, String nameHint)
-            throws RepositoryException, IOException {
-
-        // open zip packages
-        if (pkg.getArchive().getJcrRoot() == null) {
-            String msg = "Zip File is not a content package. Missing 'jcr_root'.";
-            log.error(msg);
-            pkg.close();
-            throw new IOException(msg);
-        }
-
-        // invalidate pid if path is unknown
-        PackageId pid = pkg.getId();
-        if (pid == null) {
-            if (nameHint == null || nameHint.length() == 0) {
-                throw new IOException("Package does not contain a path specification and not name hint is given.");
-            }
-            pid = new PackageId(nameHint);
-        }
-        if (!pid.isValid()) {
-            throw new RepositoryException("Unable to create package. Illegal package name.");
-        }
-
-        // create parent node
-        String path = getInstallationPath(pid) + ".zip";
-        String parentPath = Text.getRelativeParent(path, 1);
-        String name = Text.getName(path);
-        Node parent = mkdir(parentPath, false);
-
-        // remember installation state properties (GRANITE-2018)
-        JcrPackageDefinitionImpl.State state = null;
-
-        if (parent.hasNode(name)) {
-            JcrPackage oldPackage = new JcrPackageImpl(this, parent.getNode(name));
-            JcrPackageDefinitionImpl oldDef = (JcrPackageDefinitionImpl) oldPackage.getDefinition();
-            if (oldDef != null) {
-                state = oldDef.getState();
-            }
-
-            if (replace) {
-                parent.getNode(name).remove();
-            } else {
-                throw new ItemExistsException("Package already exists: " + path);
-            }
-        }
-        JcrPackage jcrPack = null;
         try {
-            jcrPack = createNew(parent, pid, pkg, false);
-            JcrPackageDefinitionImpl def = (JcrPackageDefinitionImpl) jcrPack.getDefinition();
-            if (state != null) {
-                def.setState(state);
-            }
-            dispatch(PackageEvent.Type.UPLOAD, pid, null);
-            return jcrPack;
-        } finally {
-            if (jcrPack == null) {
-                session.refresh(false);
-            } else {
-                session.save();
-            }
+            return registry.upload(pack, replace);
+        } catch (PackageExistsException e) {
+            throw new ItemExistsException(e.getMessage(), e);
         }
     }
 
@@ -444,7 +247,7 @@ public class JcrPackageManagerImpl exten
         if (folder == null) {
             folder = getPackageRoot();
         }
-        return createNew(folder, new PackageId(name), null, true);
+        return registry.createNew(folder, new PackageId(name), null, true);
     }
 
     /**
@@ -462,114 +265,21 @@ public class JcrPackageManagerImpl exten
     @Override
     public JcrPackage create(String group, String name, String version)
             throws RepositoryException, IOException {
-        // sanitize name
-        String ext = Text.getName(name, '.');
-        if ("zip".equals(ext) || "jar".equals(ext)) {
-            name = name.substring(0, name.length() - 4);
-        }
-        if (!PackageId.isValid(group, name, version)) {
-            throw new RepositoryException("Unable to create package. Illegal package name.");
-        }
-        PackageId pid = new PackageId(group, name, version);
-        Node folder = mkdir(Text.getRelativeParent(getInstallationPath(pid), 1), false);
-        return createNew(folder, pid, null, true);
+        return registry.create(group, name, version);
     }
 
     /**
-     * Creates a new jcr vault package.
-     *
-     * @param parent the parent node
-     * @param pid the package id of the new package.
-     * @param pack the underlying zip package or null.
-     * @param autoSave if {@code true} the changes are persisted immediately
-     * @return the created jcr vault package.
-     * @throws RepositoryException if an repository error occurs
-     * @throws IOException if an I/O error occurs
-     *
-     * @since 2.3.0
-     */
-    @Nonnull
-    public JcrPackage createNew(@Nonnull Node parent, @Nonnull PackageId pid, @Nullable VaultPackage pack, boolean autoSave)
-            throws RepositoryException, IOException {
-        Node node = parent.addNode(Text.getName(getInstallationPath(pid) + ".zip"), JcrConstants.NT_FILE);
-        Node content = node.addNode(JcrConstants.JCR_CONTENT, JcrConstants.NT_RESOURCE);
-        content.addMixin(JcrPackage.NT_VLT_PACKAGE);
-        Node defNode = content.addNode(JcrPackage.NN_VLT_DEFINITION);
-        JcrPackageDefinition def = new JcrPackageDefinitionImpl(defNode);
-        def.set(JcrPackageDefinition.PN_NAME, pid.getName(), false);
-        def.set(JcrPackageDefinition.PN_GROUP, pid.getGroup(), false);
-        def.set(JcrPackageDefinition.PN_VERSION, pid.getVersionString(), false);
-        def.touch(null, false);
-        content.setProperty(JcrConstants.JCR_LASTMODIFIED, Calendar.getInstance());
-        content.setProperty(JcrConstants.JCR_MIMETYPE, JcrPackage.MIME_TYPE);
-        InputStream in = new ByteArrayInputStream(new byte[0]);
-        try {
-            if (pack != null && pack.getFile() != null) {
-                in = FileUtils.openInputStream(pack.getFile());
-            }
-            // stay jcr 1.0 compatible
-            //noinspection deprecation
-            content.setProperty(JcrConstants.JCR_DATA, in);
-            if (pack != null) {
-                def.unwrap(pack, true, false);
-            }
-            if (autoSave) {
-                parent.getSession().save();
-            }
-        } finally {
-            IOUtils.closeQuietly(in);
-        }
-        dispatch(PackageEvent.Type.CREATE, pid, null);
-        return new JcrPackageImpl(this, node, (ZipVaultPackage) pack);
-    }
-
-    /**
-     * Creates a new jcr vault package.
-     *
-     * @param parent the parent node
-     * @param pid the package id of the new package.
-     * @param bin the binary containing the zip
-     * @param archive the archive with the meta data
-     * @return the created jcr vault package.
-     * @throws RepositoryException if an repository error occurs
-     * @throws IOException if an I/O error occurs
-     *
-     * @since 3.1
-     */
-    @Nonnull
-    public JcrPackage createNew(@Nonnull Node parent, @Nonnull PackageId pid, @Nonnull Binary bin, @Nonnull MemoryArchive archive)
-            throws RepositoryException, IOException {
-        Node node = parent.addNode(Text.getName(getInstallationPath(pid) + ".zip"), JcrConstants.NT_FILE);
-        Node content = node.addNode(JcrConstants.JCR_CONTENT, JcrConstants.NT_RESOURCE);
-        content.addMixin(JcrPackage.NT_VLT_PACKAGE);
-        Node defNode = content.addNode(JcrPackage.NN_VLT_DEFINITION);
-        JcrPackageDefinitionImpl def = new JcrPackageDefinitionImpl(defNode);
-        def.set(JcrPackageDefinition.PN_NAME, pid.getName(), false);
-        def.set(JcrPackageDefinition.PN_GROUP, pid.getGroup(), false);
-        def.set(JcrPackageDefinition.PN_VERSION, pid.getVersionString(), false);
-        def.touch(null, false);
-        content.setProperty(JcrConstants.JCR_LASTMODIFIED, Calendar.getInstance());
-        content.setProperty(JcrConstants.JCR_MIMETYPE, JcrPackage.MIME_TYPE);
-        content.setProperty(JcrConstants.JCR_DATA, bin);
-        def.unwrap(archive, false);
-        dispatch(PackageEvent.Type.CREATE, pid, null);
-        return new JcrPackageImpl(this, node);
-    }
-
-
-    /**
      * {@inheritDoc}
      */
     @Override
     public void remove(JcrPackage pack) throws RepositoryException {
-        PackageId pid = pack.getDefinition().getId();
-        JcrPackage snap = pack.getSnapshot();
-        if (snap != null) {
-            snap.getNode().remove();
-        }
-        pack.getNode().remove();
-        session.save();
-        dispatch(PackageEvent.Type.REMOVE, pid, null);
+        try {
+            registry.remove(pack.getDefinition().getId());
+        } catch (IOException e) {
+            throw unwrapRepositoryException(e);
+        } catch (NoSuchPackageException e) {
+            // old implementation ignored this ignore
+        }
     }
 
     /**
@@ -587,44 +297,7 @@ public class JcrPackageManagerImpl exten
     @Override
     public JcrPackage rename(JcrPackage pack, String group, String name, String version)
             throws PackageException, RepositoryException {
-        if (!pack.isValid()) {
-            throw new PackageException("Package is not valid.");
-        }
-        if (pack.getSize() > 0 && !pack.getDefinition().isUnwrapped()) {
-            throw new PackageException("Package definition not unwrapped.");
-        }
-        if (!PackageId.isValid(group, name, version)) {
-            throw new RepositoryException("Unable to rename package. Illegal package name.");
-        }
-
-        JcrPackageDefinition def = pack.getDefinition();
-        PackageId id = def.getId();
-        PackageId newId = new PackageId(
-                group == null ? id.getGroup() : group,
-                name == null ? id.getName() : name,
-                version == null ? id.getVersion() : Version.create(version)
-        );
-        String dstPath = getInstallationPath(newId) + ".zip";
-        if (id.equals(newId) && pack.getNode().getPath().equals(dstPath)) {
-            log.debug("Package id not changed. won't rename.");
-            return pack;
-        }
-        def.setId(newId, false);
-
-        // only move if not already at correct location
-        if (!pack.getNode().getPath().equals(dstPath)) {
-            if (session.nodeExists(dstPath)) {
-                throw new PackageException("Node at " + dstPath + " already exists.");
-            }
-            // ensure parent path exists
-            mkdir(Text.getRelativeParent(dstPath, 1), false);
-            session.move(pack.getNode().getPath(), dstPath);
-        }
-
-        session.save();
-        Node newNode = session.getNode(dstPath);
-        dispatch(PackageEvent.Type.RENAME, id, new PackageId[]{newId});
-        return open(newNode);
+        return registry.rename(pack, group, name, version);
     }
 
     /**
@@ -753,14 +426,6 @@ public class JcrPackageManagerImpl exten
 
 
     /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Node getPackageRoot() throws RepositoryException {
-        return getPackageRoot(false);
-    }
-
-    /**
      * yet another Convenience method to create intermediate nodes.
      * @param path path to create
      * @param autoSave if {@code true} all changes are automatically persisted
@@ -768,61 +433,15 @@ public class JcrPackageManagerImpl exten
      * @throws RepositoryException if an error occurrs
      */
     protected Node mkdir(String path, boolean autoSave) throws RepositoryException {
-        if (session.nodeExists(path)) {
-            return session.getNode(path);
-        }
-        String parentPath = Text.getRelativeParent(path, 1);
-        if (path == null || ("/".equals(path) && parentPath.equals(path))) {
-            throw new RepositoryException("could not crete intermediate nodes");
-        }
-        Node parent = mkdir(parentPath, autoSave);
-        Node node = null;
-        RepositoryException lastError = null;
-        for (int i=0; node == null && i<FOLDER_TYPES.length; i++) {
-            try {
-                node = parent.addNode(Text.getName(path), FOLDER_TYPES[i]);
-            } catch (RepositoryException e) {
-                lastError = e;
-            }
-        }
-        if (node == null) {
-            throw lastError;
-        }
-        if (autoSave) {
-            parent.getSession().save();
-        }
-        return node;
+        return registry.mkdir(path, autoSave);
     }
 
     /**
-     * Initializes vlt node types (might not be the correct location)
+     * {@inheritDoc}
      */
-    private void initNodeTypes() {
-        // check if node types are registered
-        try {
-            session.getWorkspace().getNodeTypeManager().getNodeType(JcrPackage.NT_VLT_PACKAGE);
-            // also check/register nodetypes needed for assembly
-            session.getWorkspace().getNodeTypeManager().getNodeType("vlt:HierarchyNode");
-            session.getWorkspace().getNodeTypeManager().getNodeType("vlt:FullCoverage");
-            return;
-        } catch (RepositoryException e) {
-            // ignore
-        }
-        InputStream in = null;
-        try {
-            in = getClass().getResourceAsStream(DEFAULT_NODETYPES);
-            if (in == null) {
-                throw new InternalError("Could not load " + DEFAULT_NODETYPES + " resource.");
-            }
-            NodeTypeInstaller installer = ServiceProviderFactory.getProvider().getDefaultNodeTypeInstaller(session);
-            CNDReader types = ServiceProviderFactory.getProvider().getCNDReader();
-            types.read(new InputStreamReader(in, "utf8"), DEFAULT_NODETYPES, null);
-            installer.install(null, types);
-        } catch (Throwable e) {
-            log.warn("Error while registering nodetypes. Package installation might not work correctly.", e);
-        } finally {
-            IOUtils.closeQuietly(in);
-        }
+    @Override
+    public Node getPackageRoot() throws RepositoryException {
+        return registry.getPackageRoot(false);
     }
 
     /**
@@ -830,34 +449,7 @@ public class JcrPackageManagerImpl exten
      */
     @Override
     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
-                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);
-                }
-                packRoot = pack;
-            }
-        }
-        return packRoot;
+        return registry.getPackageRoot(noCreate);
     }
 
     /**
@@ -941,7 +533,7 @@ public class JcrPackageManagerImpl exten
                 if (".snapshot".equals(child.getName())) {
                     continue;
                 }
-                JcrPackageImpl pack = new JcrPackageImpl(this, child);
+                JcrPackageImpl pack = new JcrPackageImpl(registry, child);
                 if (pack.isValid()) {
                     // skip packages with illegal names
                     JcrPackageDefinition jDef = pack.getDefinition();
@@ -960,29 +552,9 @@ public class JcrPackageManagerImpl exten
         }
     }
 
-    /**
-     * Returns the path of this package. please note that since 2.3 this also
-     * includes the version, but never the extension (.zip).
-     *
-     * Note that the exact storage location is implementation detail and this method should only be used internally for
-     * backward compatibility use cases.
-     *
-     * @param pid the package id
-     * @return the path of this package
-     */
-    public static String getInstallationPath(PackageId pid) {
-        StringBuilder b = new StringBuilder(PACKAGE_ROOT_PATH_PREFIX);
-        String group = pid.getGroup();
-        if (group.length() > 0) {
-            b.append(group);
-            b.append("/");
-        }
-        b.append(pid.getName());
-        String version = pid.getVersion().toString();
-        if (version.length() > 0) {
-            b.append("-").append(version);
-        }
-        return b.toString();
+    @Override
+    public void setDispatcher(@Nullable PackageEventDispatcher dispatcher) {
+        super.setDispatcher(dispatcher);
+        registry.setDispatcher(dispatcher);
     }
-
 }
\ No newline at end of file

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/package-info.java?rev=1810052&r1=1810051&r2=1810052&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/package-info.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/package-info.java Fri Sep 29 04:16:57 2017
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-@Version("2.5.0")
+@Version("2.6.0")
 package org.apache.jackrabbit.vault.packaging;
 
 import org.osgi.annotation.versioning.Version;
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/DependencyReport.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/DependencyReport.java?rev=1810052&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/DependencyReport.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/DependencyReport.java Fri Sep 29 04:16:57 2017
@@ -0,0 +1,52 @@
+/*
+ * 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.registry;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.vault.packaging.Dependency;
+import org.apache.jackrabbit.vault.packaging.DependencyHandling;
+import org.apache.jackrabbit.vault.packaging.PackageId;
+
+/**
+ * Reports dependency usages.
+ */
+public interface DependencyReport {
+
+    /**
+     * The id of the package this report is created for.
+     * @return the package Id
+     */
+    @Nonnull
+    PackageId getId();
+
+    /**
+     * Returns the dependencies that are not resolved. If the {@link DependencyHandling} is set to strict, the package
+     * will not installed if any unresolved dependencies are listed.
+     * @return the array of unresolved dependencies.
+     */
+    @Nonnull
+    Dependency[] getUnresolvedDependencies();
+
+    /**
+     * Returns a list of the installed packages that this package depends on.
+     * @return the array of resolved dependencies
+     */
+    @Nonnull
+    PackageId[] getResolvedDependencies();
+
+}
\ No newline at end of file

Copied: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/ExecutionPlan.java (from r1805059, jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java)
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/ExecutionPlan.java?p2=jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/ExecutionPlan.java&p1=jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java&r1=1805059&r2=1810052&rev=1810052&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/ExecutionPlan.java Fri Sep 29 04:16:57 2017
@@ -14,27 +14,43 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.jackrabbit.vault.packaging.registry;
 
-package org.apache.jackrabbit.vault.packaging;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import org.osgi.annotation.versioning.ProviderType;
 
 /**
- * {@code PackageException}...
+ * Holds a list of tasks that perform package installation related operations.
  */
-public class PackageException extends Exception {
+@ProviderType
+public interface ExecutionPlan {
 
-    public PackageException() {
-        super();
-    }
-
-    public PackageException(String message) {
-        super(message);
-    }
-
-    public PackageException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public PackageException(Throwable cause) {
-        super(cause);
-    }
+    /**
+     * An id of the execution plan.
+     * @return the id.
+     */
+    @Nonnull
+    String getId();
+
+    /**
+     * Retrieves the list of all tasks
+     * @return the tasks.
+     */
+    @Nonnull
+    List<PackageTask> getTasks();
+
+    /**
+     * Checks if this plan has finished.
+     * @return {@code true} if executed.
+     */
+    boolean isExecuted();
+
+    /**
+     * checks if this plan has error
+     * @return {@code true} if it has errors.
+     */
+    boolean hasErrors();
 }
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/ExecutionPlanBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/ExecutionPlanBuilder.java?rev=1810052&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/ExecutionPlanBuilder.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/ExecutionPlanBuilder.java Fri Sep 29 04:16:57 2017
@@ -0,0 +1,95 @@
+/*
+ * 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.registry;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.annotation.Nonnull;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener;
+import org.apache.jackrabbit.vault.packaging.PackageException;
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * Helps to construct an execution plan that can be serialized and given to the packaging backend for execution.
+ */
+@ProviderType
+public interface ExecutionPlanBuilder {
+
+    /**
+     * Loads the tasks from a serialized plan and replaces the plans already in this builder.
+     * @param in input stream to the data.
+     * @return this
+     * @throws IOException if an I/O error occurrs.
+     */
+    @Nonnull
+    ExecutionPlanBuilder load(@Nonnull InputStream in) throws IOException;
+
+    /**
+     * Serializes the tasks of this plan.
+     * @param out the output stream
+     * @return this
+     * @throws IOException if an I/O error occurrs.
+     * @throws PackageException if this builder does not have valid tasks.
+     */
+    @Nonnull
+    ExecutionPlanBuilder save(@Nonnull OutputStream out) throws IOException, PackageException;
+
+    /**
+     * Adds a new task to this builder.
+     * @return an package task builder that helps to assemble the task.
+     */
+    @Nonnull
+    PackageTaskBuilder addTask();
+
+    /**
+     * Validates this plan.
+     * @return this.
+     * @throws IOException if an I/O error occurrs.
+     * @throws PackageException if the plan is not valid.
+     */
+    @Nonnull
+    ExecutionPlanBuilder validate() throws IOException, PackageException;
+
+    /**
+     * Sets the JCR session for this execution plan.
+     * @param session the session
+     * @return this.
+     */
+    @Nonnull
+    ExecutionPlanBuilder with(@Nonnull Session session);
+
+    /**
+     * Sets the progress tracker listener for this plan.
+     * @param listener the listener
+     * @return this.
+     */
+    @Nonnull
+    ExecutionPlanBuilder with(@Nonnull ProgressTrackerListener listener);
+
+    /**
+     * builds an executes the plan synchronously.
+     * @return the execution plan.
+     * @throws IOException if an I/O error occurrs.
+     * @throws PackageException if a package operation fails.
+     */
+    @Nonnull
+    ExecutionPlan execute() throws IOException, PackageException;
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/PackageRegistry.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/PackageRegistry.java?rev=1810052&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/PackageRegistry.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/PackageRegistry.java Fri Sep 29 04:16:57 2017
@@ -0,0 +1,157 @@
+/*
+ * 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.registry;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.jackrabbit.vault.packaging.Dependency;
+import org.apache.jackrabbit.vault.packaging.NoSuchPackageException;
+import org.apache.jackrabbit.vault.packaging.PackageExistsException;
+import org.apache.jackrabbit.vault.packaging.PackageId;
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * The package registry is the next generation {@link org.apache.jackrabbit.vault.packaging.PackageManager} and
+ * {@link org.apache.jackrabbit.vault.packaging.JcrPackageManager}. It defines storage independent methods to
+ * register (upload), enumerate and remove packages. The installation lifecycle of the packages is provided via
+ * {@link ExecutionPlan}s.
+ */
+@ProviderType
+public interface PackageRegistry {
+
+    /**
+     * Checks if this registry contains the package with the given id.
+     * @param id the package id.
+     * @return {@code true} if the package is registered.
+     * @throws IOException if an I/O error occurrs.
+     */
+    boolean contains(@Nonnull PackageId id) throws IOException;
+
+    /**
+     * Returns as set of all packages registered in this registry.
+     * @return a set of package ids.
+     * @throws IOException if an I/O error occurrs.
+     */
+    @Nonnull
+    Set<PackageId> packages() throws IOException;
+
+    /**
+     * Opens the package with the given id.
+     * @param id the package id
+     * @return the package or {@code null} if it does not exists.
+     * @throws IOException if an I/O error occurrs.
+     */
+    @Nullable
+    RegisteredPackage open(@Nonnull PackageId id) throws IOException;
+
+    /**
+     * Registers a package provided via an input stream. The method fails, if a package with the same id already exists,
+     * and {@code replace} is set to {@code false}. otherwise the existing package is replaced.
+     *
+     * @param in the input stream to the package data
+     * @param replace {@code true} if existing package should be replaced.
+     * @return the new package id.
+     * @throws IOException if an I/O error occurrs.
+     * @throws PackageExistsException if the package exists and {@code replace} is {@code false}.
+     */
+    @Nonnull
+    PackageId register(@Nonnull InputStream in, boolean replace) throws IOException, PackageExistsException;
+
+    /**
+     * Registers a package provided via a file. The method fails, if a package with the same id already exists,
+     * and {@code replace} is set to {@code false}; otherwise the existing package is replaced.
+     *
+     * @param file the file to the package data
+     * @param replace {@code true} if existing package should be replaced.
+     * @return the new package id.
+     * @throws IOException if an I/O error occurrs.
+     * @throws PackageExistsException if the package exists and {@code replace} is {@code false}.
+     */
+    @Nonnull
+    PackageId register(@Nonnull File file, boolean replace) throws IOException, PackageExistsException;
+
+    /**
+     * Registers a package provided via an external file. The binary data of the package will not be copied into the
+     * underlying persistence but only be referenced. Removing such a linked package afterwards will not delete the
+     * original file.
+     *
+     * The method fails, if a package with the same id already exists,
+     * and {@code replace} is set to {@code false}; otherwise the existing package is replaced.
+     *
+     * @param file the file to the package data.
+     * @param replace {@code true} if existing package should be replaced.
+     * @return the new package id.
+     * @throws IOException if an I/O error occurrs.
+     * @throws PackageExistsException if the package exists and {@code replace} is {@code false}.
+     */
+    @Nonnull
+    PackageId registerExternal(@Nonnull File file, boolean replace) throws IOException, PackageExistsException;
+
+    /**
+     * Removes the package from this registry.
+     * @param id the id of the package to remove
+     * @throws IOException if an I/O error occurrs.
+     * @throws NoSuchPackageException if the package does not exist
+     */
+    void remove(@Nonnull PackageId id) throws IOException, NoSuchPackageException;
+
+    /**
+     * Creates a dependency report that lists the resolved and unresolved dependencies.
+     * @param id the package id.
+     * @param onlyInstalled if {@code true} only installed packages are used for resolution
+     * @return the report
+     * @throws IOException if an error accessing the repository occurrs
+     * @throws NoSuchPackageException if the package with the given {@code id} does not exist.
+     */
+    @Nonnull
+    DependencyReport analyzeDependencies(@Nonnull PackageId id, boolean onlyInstalled) throws IOException, NoSuchPackageException;
+
+    /**
+     * Tries to resolve the given dependency and returns the id of the package that matches the dependency filter best.
+     * @param dependency the dependency to resolve against.
+     * @param onlyInstalled if {@code true} only installed packages are respected.
+     * @return the package id or {@code null}
+     * @throws IOException if an I/O error occurrs.
+     */
+    @Nullable
+    PackageId resolve(@Nonnull Dependency dependency, boolean onlyInstalled) throws IOException;
+
+    /**
+     * Returns the package ids of installed packages that depend on the given package.
+     *
+     * @param id the package id to search for
+     * @return the array of package ids.
+     * @throws IOException if an I/O error occurs.
+     */
+    @Nonnull
+    PackageId[] usage(@Nonnull PackageId id) throws IOException;
+
+    /**
+     * Creates a new execution plan builder. The builder allows to create an execution plan for package installation
+     * related tasks.
+     *
+     * @return a new builder
+     */
+    @Nonnull
+    ExecutionPlanBuilder createExecutionPlan();
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/PackageTask.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/PackageTask.java?rev=1810052&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/PackageTask.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/PackageTask.java Fri Sep 29 04:16:57 2017
@@ -0,0 +1,106 @@
+/*
+ * 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.registry;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.jackrabbit.vault.packaging.PackageId;
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * Describes a package operation task.
+ */
+@ProviderType
+public interface PackageTask {
+
+    /**
+     * Task type
+     */
+    enum Type {
+
+        /**
+         * Package installation
+         */
+        INSTALL,
+
+        /**
+         * Package uninstallation
+         */
+        UNINSTALL,
+
+        /**
+         * Package removal
+         */
+        REMOVE,
+
+        /**
+         * Package extraction
+         */
+        EXTRACT
+    }
+
+    /**
+     * Task state
+     */
+    enum State {
+        /**
+         * task is new
+         */
+        NEW,
+        /**
+         * Task is running
+         */
+        RUNNING,
+        /**
+         * Task has completed
+         */
+        COMPLETED,
+        /**
+         * Task has errors
+         */
+        ERROR
+    }
+
+    /**
+     * Returns the package id of this task.
+     * @return the package id.
+     */
+    @Nonnull
+    PackageId getPackageId();
+
+    /**
+     * Returns the task type.
+     * @return the task type.
+     */
+    @Nonnull
+    Type getType();
+
+    /**
+     * Returns the task state
+     * @return the task state
+     */
+    @Nonnull
+    State getState();
+
+    /**
+     * Returns the error if there was one.
+     * @return the error
+     */
+    @Nullable
+    Throwable getError();
+}
\ No newline at end of file

Copied: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/PackageTaskBuilder.java (from r1805059, jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java)
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/PackageTaskBuilder.java?p2=jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/PackageTaskBuilder.java&p1=jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java&r1=1805059&r2=1810052&rev=1810052&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/PackageTaskBuilder.java Fri Sep 29 04:16:57 2017
@@ -14,27 +14,33 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.jackrabbit.vault.packaging.registry;
 
-package org.apache.jackrabbit.vault.packaging;
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.vault.packaging.PackageId;
+import org.osgi.annotation.versioning.ProviderType;
 
 /**
- * {@code PackageException}...
+ * {@code ExecutionTaskBuilder}...
  */
-public class PackageException extends Exception {
+@ProviderType
+public interface PackageTaskBuilder {
+
+    /**
+     * Sets the package id of this task.
+     * @param id the package id
+     * @return this.
+     */
+    @Nonnull
+    PackageTaskBuilder with(@Nonnull PackageId id);
+
+    /**
+     * Sets the type of this task
+     * @param type the type
+     * @return this.
+     */
+    @Nonnull
+    ExecutionPlanBuilder with(@Nonnull PackageTask.Type type);
 
-    public PackageException() {
-        super();
-    }
-
-    public PackageException(String message) {
-        super(message);
-    }
-
-    public PackageException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public PackageException(Throwable cause) {
-        super(cause);
-    }
 }
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/RegisteredPackage.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/RegisteredPackage.java?rev=1810052&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/RegisteredPackage.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/RegisteredPackage.java Fri Sep 29 04:16:57 2017
@@ -0,0 +1,74 @@
+/*
+ * 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.registry;
+
+import java.io.IOException;
+import java.util.Calendar;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.jackrabbit.vault.packaging.PackageId;
+import org.apache.jackrabbit.vault.packaging.VaultPackage;
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * {@code RegisteredPackage}...
+ */
+@ProviderType
+public interface RegisteredPackage extends Comparable<RegisteredPackage>, AutoCloseable {
+
+    /**
+     * Returns the id of this package
+     * @return the id of this package.
+     */
+    @Nonnull
+    PackageId getId();
+
+    /**
+     * Returns the vault package stored in the data of this package
+     * @return the package
+     * @throws IOException if an I/O error occurs
+     */
+    @Nonnull
+    VaultPackage getPackage() throws IOException;
+
+    /**
+     * Returns the size of the underlying package.
+     * @return the size in bytes
+     */
+    long getSize();
+
+    /**
+     * Checks if this package is installed.
+     * @return {@code true} if this package is installed.
+     */
+    boolean isInstalled();
+
+    /**
+     * Returns the date when the package was installed
+     * @return the installed date or {@code null} if not installed.
+     */
+    @Nullable
+    Calendar getInstallationTime();
+
+    /**
+     * Closes this package and releases underlying data.
+     */
+    void close();
+
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/DependencyReportImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/DependencyReportImpl.java?rev=1810052&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/DependencyReportImpl.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/DependencyReportImpl.java Fri Sep 29 04:16:57 2017
@@ -0,0 +1,59 @@
+/*
+ * 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.registry.impl;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.vault.packaging.Dependency;
+import org.apache.jackrabbit.vault.packaging.PackageId;
+import org.apache.jackrabbit.vault.packaging.registry.DependencyReport;
+
+/**
+ * {@code UsageReportImpl}...
+ */
+public class DependencyReportImpl implements DependencyReport {
+
+    private final PackageId id;
+
+    private final Dependency[] unresolved;
+
+    private final PackageId[] resolved;
+
+    public DependencyReportImpl(PackageId id, Dependency[] unresolved, PackageId[] resolved) {
+        this.id = id;
+        this.unresolved = unresolved;
+        this.resolved = resolved;
+    }
+
+    @Nonnull
+    @Override
+    public PackageId getId() {
+        return id;
+    }
+
+    @Nonnull
+    @Override
+    public Dependency[] getUnresolvedDependencies() {
+        return unresolved;
+    }
+
+    @Nonnull
+    @Override
+    public PackageId[] getResolvedDependencies() {
+        return resolved;
+    }
+}
\ No newline at end of file