You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cs...@apache.org on 2019/07/22 18:20:26 UTC

[sling-org-apache-sling-distribution-core] branch SLING-8591-3 created (now 1387a7d)

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

cschneider pushed a change to branch SLING-8591-3
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-distribution-core.git.


      at 1387a7d  SLING-8591 - Hook to support custom code when installing or deleting distribution packages

This branch includes the following new commits:

     new 1387a7d  SLING-8591 - Hook to support custom code when installing or deleting distribution packages

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[sling-org-apache-sling-distribution-core] 01/01: SLING-8591 - Hook to support custom code when installing or deleting distribution packages

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

cschneider pushed a commit to branch SLING-8591-3
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-distribution-core.git

commit 1387a7da50cd6e02e99bbd4063003c646a88de70
Author: Christian Schneider <cs...@adobe.com>
AuthorDate: Mon Jul 22 20:19:41 2019 +0200

    SLING-8591 - Hook to support custom code when installing or deleting distribution packages
---
 .../distribution/packaging/PackageInstallHook.java | 46 +++++++++++++
 .../impl/AbstractDistributionPackageBuilder.java   | 13 +++-
 .../impl/FileDistributionPackageBuilder.java       |  6 +-
 .../impl/InMemoryDistributionPackageBuilder.java   |  6 +-
 .../packaging/impl/NoopPackageInstallHook.java     | 45 ++++++++++++
 .../impl/ResourceDistributionPackageBuilder.java   |  6 +-
 .../sling/distribution/packaging/package-info.java |  2 +-
 .../impl/DistributionPackageBuilderFactory.java    | 11 ++-
 .../VaultDistributionPackageBuilderFactory.java    | 11 ++-
 .../sling/distribution/DistributionBaseIT.java     |  3 -
 .../packaging/DistributionPackageInfoTest.java}    | 11 ++-
 .../impl/FileDistributionPackageBuilderTest.java   |  4 +-
 .../InMemoryDistributionPackageBuilderTest.java    | 79 ++++++++++++++++++++--
 .../impl/SimpleDistributionPackageTest.java        | 52 +++++++++++++-
 .../LocalDistributionPackageImporterTest.java      |  5 +-
 .../queue/impl/resource/ResourceQueueIT.java       |  2 +
 src/test/resources/logback.xml                     | 30 ++++++++
 17 files changed, 302 insertions(+), 30 deletions(-)

diff --git a/src/main/java/org/apache/sling/distribution/packaging/PackageInstallHook.java b/src/main/java/org/apache/sling/distribution/packaging/PackageInstallHook.java
new file mode 100644
index 0000000..ad806fc
--- /dev/null
+++ b/src/main/java/org/apache/sling/distribution/packaging/PackageInstallHook.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.distribution.packaging;
+
+import org.apache.sling.api.resource.ResourceResolver;
+
+import aQute.bnd.annotation.ProviderType;
+
+/**
+ * Callback that allows to run code after a DistributionPackage is installed.
+ */
+@ProviderType
+public interface PackageInstallHook {
+    public static final String NOOP_NAME = "noop_install_hook";
+    public static final String NOOP_FILTER = "(name=" + PackageInstallHook.NOOP_NAME + ")";
+    
+    /**
+     * Will be called after a package was installed into the repository
+     * @param resourceResolver 
+     * @param distPackage
+     */
+    void onPostAdd(ResourceResolver resourceResolver, DistributionPackage distPackage);
+    
+    /**
+     * Will be called after a package was installed into the repository
+     * @param resourceResolver 
+     * @param distPackage
+     */
+    void onPreRemove(ResourceResolver resourceResolver, DistributionPackage distPackage);
+}
diff --git a/src/main/java/org/apache/sling/distribution/packaging/impl/AbstractDistributionPackageBuilder.java b/src/main/java/org/apache/sling/distribution/packaging/impl/AbstractDistributionPackageBuilder.java
index 0993667..e6f090d 100644
--- a/src/main/java/org/apache/sling/distribution/packaging/impl/AbstractDistributionPackageBuilder.java
+++ b/src/main/java/org/apache/sling/distribution/packaging/impl/AbstractDistributionPackageBuilder.java
@@ -35,6 +35,7 @@ import org.apache.sling.distribution.common.DistributionException;
 import org.apache.sling.distribution.packaging.DistributionPackage;
 import org.apache.sling.distribution.packaging.DistributionPackageBuilder;
 import org.apache.sling.distribution.packaging.DistributionPackageInfo;
+import org.apache.sling.distribution.packaging.PackageInstallHook;
 import org.apache.sling.distribution.serialization.impl.vlt.VltUtils;
 import org.apache.sling.distribution.util.DistributionJcrUtils;
 import org.jetbrains.annotations.NotNull;
@@ -51,8 +52,11 @@ public abstract class AbstractDistributionPackageBuilder implements Distribution
 
     private final String type;
 
-    AbstractDistributionPackageBuilder(String type) {
+    private PackageInstallHook installHook;
+
+    AbstractDistributionPackageBuilder(String type, PackageInstallHook installHook) {
         this.type = type;
+        this.installHook = installHook;
     }
 
     public String getType() {
@@ -170,6 +174,7 @@ public abstract class AbstractDistributionPackageBuilder implements Distribution
         Session session = null;
         try {
             if (distributionPackage != null) {
+                installHook.onPreRemove(resourceResolver, distributionPackage);
                 session = getSession(resourceResolver);
                 for (String path : distributionPackage.getInfo().getPaths()) {
                     if (session.itemExists(path)) {
@@ -193,7 +198,11 @@ public abstract class AbstractDistributionPackageBuilder implements Distribution
         InputStream inputStream = null;
         try {
             inputStream = distributionPackage.createInputStream();
-            return installPackageInternal(resourceResolver, inputStream);
+            boolean isInstalled = installPackageInternal(resourceResolver, inputStream);
+            if (isInstalled) {
+                installHook.onPostAdd(resourceResolver, distributionPackage);
+            }
+            return isInstalled;
         } catch (IOException e) {
             throw new DistributionException(e);
         } finally {
diff --git a/src/main/java/org/apache/sling/distribution/packaging/impl/FileDistributionPackageBuilder.java b/src/main/java/org/apache/sling/distribution/packaging/impl/FileDistributionPackageBuilder.java
index a79a7a2..35dbf8b 100644
--- a/src/main/java/org/apache/sling/distribution/packaging/impl/FileDistributionPackageBuilder.java
+++ b/src/main/java/org/apache/sling/distribution/packaging/impl/FileDistributionPackageBuilder.java
@@ -37,6 +37,7 @@ import org.apache.sling.distribution.DistributionRequest;
 import org.apache.sling.distribution.common.DistributionException;
 import org.apache.sling.distribution.packaging.DistributionPackage;
 import org.apache.sling.distribution.packaging.DistributionPackageBuilder;
+import org.apache.sling.distribution.packaging.PackageInstallHook;
 import org.apache.sling.distribution.serialization.DistributionContentSerializer;
 import org.apache.sling.distribution.serialization.DistributionExportFilter;
 import org.apache.sling.distribution.serialization.DistributionExportOptions;
@@ -64,8 +65,9 @@ public class FileDistributionPackageBuilder extends AbstractDistributionPackageB
                                           DistributionContentSerializer distributionContentSerializer,
                                           String tempFilesFolder,
                                           String digestAlgorithm, String[] nodeFilters,
-                                          String[] propertyFilters) {
-        super(type);
+                                          String[] propertyFilters,
+                                          PackageInstallHook postInstallHook) {
+        super(type, postInstallHook);
         this.distributionContentSerializer = distributionContentSerializer;
         this.nodeFilters = VltUtils.parseFilters(nodeFilters);
         this.propertyFilters = VltUtils.parseFilters(propertyFilters);
diff --git a/src/main/java/org/apache/sling/distribution/packaging/impl/InMemoryDistributionPackageBuilder.java b/src/main/java/org/apache/sling/distribution/packaging/impl/InMemoryDistributionPackageBuilder.java
index d55b77e..d7e7cd1 100644
--- a/src/main/java/org/apache/sling/distribution/packaging/impl/InMemoryDistributionPackageBuilder.java
+++ b/src/main/java/org/apache/sling/distribution/packaging/impl/InMemoryDistributionPackageBuilder.java
@@ -33,6 +33,7 @@ import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.distribution.DistributionRequest;
 import org.apache.sling.distribution.common.DistributionException;
 import org.apache.sling.distribution.packaging.DistributionPackage;
+import org.apache.sling.distribution.packaging.PackageInstallHook;
 import org.apache.sling.distribution.serialization.DistributionContentSerializer;
 import org.apache.sling.distribution.serialization.DistributionExportFilter;
 import org.apache.sling.distribution.serialization.DistributionExportOptions;
@@ -58,8 +59,9 @@ public class InMemoryDistributionPackageBuilder extends AbstractDistributionPack
     public InMemoryDistributionPackageBuilder(@NotNull String type,
                                               @NotNull DistributionContentSerializer serializer,
                                               @Nullable String[] nodeFilters,
-                                              @Nullable String[] propertyFilters) {
-        super(type);
+                                              @Nullable String[] propertyFilters,
+                                              PackageInstallHook postInstallHook) {
+        super(type, postInstallHook);
         this.serializer = serializer;
         this.nodeFilters = VltUtils.parseFilters(nodeFilters);
         this.propertyFilters = VltUtils.parseFilters(propertyFilters);
diff --git a/src/main/java/org/apache/sling/distribution/packaging/impl/NoopPackageInstallHook.java b/src/main/java/org/apache/sling/distribution/packaging/impl/NoopPackageInstallHook.java
new file mode 100644
index 0000000..a87f29c
--- /dev/null
+++ b/src/main/java/org/apache/sling/distribution/packaging/impl/NoopPackageInstallHook.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.distribution.packaging.impl;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.distribution.packaging.DistributionPackage;
+import org.apache.sling.distribution.packaging.PackageInstallHook;
+
+/**
+ * Default hook that simply does nothing
+ */
+@Component
+@Service(PackageInstallHook.class)
+@Property(name = "name", value = "Builder name: {name}")
+public class NoopPackageInstallHook implements PackageInstallHook {
+
+    @Override
+    public void onPostAdd(ResourceResolver resourceResolver, DistributionPackage distPackage) {
+        // Noop
+    }
+
+    @Override
+    public void onPreRemove(ResourceResolver resourceResolver, DistributionPackage distPackage) {
+        // Noop
+    }
+}
diff --git a/src/main/java/org/apache/sling/distribution/packaging/impl/ResourceDistributionPackageBuilder.java b/src/main/java/org/apache/sling/distribution/packaging/impl/ResourceDistributionPackageBuilder.java
index 919d3d9..ada62d0 100644
--- a/src/main/java/org/apache/sling/distribution/packaging/impl/ResourceDistributionPackageBuilder.java
+++ b/src/main/java/org/apache/sling/distribution/packaging/impl/ResourceDistributionPackageBuilder.java
@@ -44,6 +44,7 @@ import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.distribution.DistributionRequest;
 import org.apache.sling.distribution.common.DistributionException;
 import org.apache.sling.distribution.packaging.DistributionPackage;
+import org.apache.sling.distribution.packaging.PackageInstallHook;
 import org.apache.sling.distribution.serialization.DistributionContentSerializer;
 import org.apache.sling.distribution.serialization.DistributionExportFilter;
 import org.apache.sling.distribution.serialization.DistributionExportOptions;
@@ -76,8 +77,9 @@ public class ResourceDistributionPackageBuilder extends AbstractDistributionPack
                                               MemoryUnit memoryUnit,
                                               boolean useOffHeapMemory,
                                               String digestAlgorithm, String[] nodeFilters,
-                                              String[] propertyFilters) {
-        super(type);
+                                              String[] propertyFilters, 
+                                              PackageInstallHook postInstallHook) {
+        super(type, postInstallHook);
         this.distributionContentSerializer = distributionContentSerializer;
         this.nodeFilters = VltUtils.parseFilters(nodeFilters);
         this.propertyFilters = VltUtils.parseFilters(propertyFilters);
diff --git a/src/main/java/org/apache/sling/distribution/packaging/package-info.java b/src/main/java/org/apache/sling/distribution/packaging/package-info.java
index 8f378be..e0a3160 100644
--- a/src/main/java/org/apache/sling/distribution/packaging/package-info.java
+++ b/src/main/java/org/apache/sling/distribution/packaging/package-info.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-@Version("0.0.1")
+@Version("0.1.0")
 package org.apache.sling.distribution.packaging;
 
 import aQute.bnd.annotation.Version;
diff --git a/src/main/java/org/apache/sling/distribution/serialization/impl/DistributionPackageBuilderFactory.java b/src/main/java/org/apache/sling/distribution/serialization/impl/DistributionPackageBuilderFactory.java
index 09b8c9b..7d7f30a 100644
--- a/src/main/java/org/apache/sling/distribution/serialization/impl/DistributionPackageBuilderFactory.java
+++ b/src/main/java/org/apache/sling/distribution/serialization/impl/DistributionPackageBuilderFactory.java
@@ -44,6 +44,7 @@ import org.apache.sling.distribution.monitor.impl.MonitoringDistributionPackageB
 import org.apache.sling.distribution.packaging.DistributionPackage;
 import org.apache.sling.distribution.packaging.DistributionPackageBuilder;
 import org.apache.sling.distribution.packaging.DistributionPackageInfo;
+import org.apache.sling.distribution.packaging.PackageInstallHook;
 import org.apache.sling.distribution.packaging.impl.FileDistributionPackageBuilder;
 import org.apache.sling.distribution.packaging.impl.InMemoryDistributionPackageBuilder;
 import org.apache.sling.distribution.packaging.impl.ResourceDistributionPackageBuilder;
@@ -193,6 +194,10 @@ public class DistributionPackageBuilderFactory implements DistributionPackageBui
 
     private ServiceRegistration packageCleanup = null;
 
+    @Property(name = "installHook.target", label = "install hook", description = "Hook to be called after package was installed and before package will be removed.", value = PackageInstallHook.NOOP_FILTER)
+    @Reference
+    private PackageInstallHook installHook;
+
     @Activate
     public void activate(BundleContext context,
                          Map<String, Object> config) {
@@ -209,15 +214,15 @@ public class DistributionPackageBuilderFactory implements DistributionPackageBui
 
         DistributionPackageBuilder wrapped;
         if ("file".equals(persistenceType)) {
-            wrapped = new FileDistributionPackageBuilder(contentSerializer.getName(), contentSerializer, tempFsFolder, digestAlgorithm, nodeFilters, propertyFilters);
+            wrapped = new FileDistributionPackageBuilder(contentSerializer.getName(), contentSerializer, tempFsFolder, digestAlgorithm, nodeFilters, propertyFilters, installHook);
         } else if ("inmemory".equals(persistenceType)) {
-            wrapped = new InMemoryDistributionPackageBuilder(contentSerializer.getName(), contentSerializer, nodeFilters, propertyFilters);
+            wrapped = new InMemoryDistributionPackageBuilder(contentSerializer.getName(), contentSerializer, nodeFilters, propertyFilters, installHook);
         } else {
             final int fileThreshold = PropertiesUtil.toInteger(config.get(FILE_THRESHOLD), DEFAULT_FILE_THRESHOLD_VALUE);
             String memoryUnitName = PropertiesUtil.toString(config.get(MEMORY_UNIT), DEFAULT_MEMORY_UNIT);
             final MemoryUnit memoryUnit = MemoryUnit.valueOf(memoryUnitName);
             final boolean useOffHeapMemory = PropertiesUtil.toBoolean(config.get(USE_OFF_HEAP_MEMORY), DEFAULT_USE_OFF_HEAP_MEMORY);
-            ResourceDistributionPackageBuilder resourceDistributionPackageBuilder = new ResourceDistributionPackageBuilder(contentSerializer.getName(), contentSerializer, tempFsFolder, fileThreshold, memoryUnit, useOffHeapMemory, digestAlgorithm, nodeFilters, propertyFilters);
+            ResourceDistributionPackageBuilder resourceDistributionPackageBuilder = new ResourceDistributionPackageBuilder(contentSerializer.getName(), contentSerializer, tempFsFolder, fileThreshold, memoryUnit, useOffHeapMemory, digestAlgorithm, nodeFilters, propertyFilters, installHook);
             Runnable cleanup = new ResourceDistributionPackageCleanup(resolverFactory, resourceDistributionPackageBuilder);
             Dictionary<String, Object> props = new Hashtable<String, Object>();
             props.put(Scheduler.PROPERTY_SCHEDULER_CONCURRENT, false);
diff --git a/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/VaultDistributionPackageBuilderFactory.java b/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/VaultDistributionPackageBuilderFactory.java
index cffed94..9db58a2 100644
--- a/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/VaultDistributionPackageBuilderFactory.java
+++ b/src/main/java/org/apache/sling/distribution/serialization/impl/vlt/VaultDistributionPackageBuilderFactory.java
@@ -34,6 +34,7 @@ import org.apache.sling.distribution.monitor.impl.MonitoringDistributionPackageB
 import org.apache.sling.distribution.packaging.DistributionPackage;
 import org.apache.sling.distribution.packaging.DistributionPackageBuilder;
 import org.apache.sling.distribution.packaging.DistributionPackageInfo;
+import org.apache.sling.distribution.packaging.PackageInstallHook;
 import org.apache.sling.distribution.packaging.impl.FileDistributionPackageBuilder;
 import org.apache.sling.distribution.packaging.impl.InMemoryDistributionPackageBuilder;
 import org.apache.sling.distribution.packaging.impl.ResourceDistributionPackageBuilder;
@@ -226,6 +227,10 @@ public class VaultDistributionPackageBuilderFactory implements DistributionPacka
 
     private MonitoringDistributionPackageBuilder packageBuilder;
 
+    @Property(name = "postInstallHook.target", label = "Post install hook", description = "Hook to be called after package was installed.",
+            value = PackageInstallHook.NOOP_FILTER)
+    @Reference
+    private PackageInstallHook postInstallHook;
 
     @Activate
     public void activate(BundleContext context, Map<String, Object> config) {
@@ -271,15 +276,15 @@ public class VaultDistributionPackageBuilderFactory implements DistributionPacka
 
         DistributionPackageBuilder wrapped;
         if ("filevlt".equals(type)) {
-            wrapped = new FileDistributionPackageBuilder(name, contentSerializer, tempFsFolder, digestAlgorithm, packageNodeFilters, packagePropertyFilters);
+            wrapped = new FileDistributionPackageBuilder(name, contentSerializer, tempFsFolder, digestAlgorithm, packageNodeFilters, packagePropertyFilters, postInstallHook);
         } else if ("inmemory".equals(type)) {
-            wrapped = new InMemoryDistributionPackageBuilder(name, contentSerializer, packageNodeFilters, packagePropertyFilters);
+            wrapped = new InMemoryDistributionPackageBuilder(name, contentSerializer, packageNodeFilters, packagePropertyFilters, postInstallHook);
         } else {
             final int fileThreshold = PropertiesUtil.toInteger(config.get(FILE_THRESHOLD), DEFAULT_FILE_THRESHOLD_VALUE);
             String memoryUnitName = PropertiesUtil.toString(config.get(MEMORY_UNIT), DEFAULT_MEMORY_UNIT);
             final MemoryUnit memoryUnit = MemoryUnit.valueOf(memoryUnitName);
             final boolean useOffHeapMemory = PropertiesUtil.toBoolean(config.get(USE_OFF_HEAP_MEMORY), DEFAULT_USE_OFF_HEAP_MEMORY);
-            ResourceDistributionPackageBuilder resourceDistributionPackageBuilder = new ResourceDistributionPackageBuilder(contentSerializer.getName(), contentSerializer, tempFsFolder, fileThreshold, memoryUnit, useOffHeapMemory, digestAlgorithm, packageNodeFilters, packagePropertyFilters);
+            ResourceDistributionPackageBuilder resourceDistributionPackageBuilder = new ResourceDistributionPackageBuilder(contentSerializer.getName(), contentSerializer, tempFsFolder, fileThreshold, memoryUnit, useOffHeapMemory, digestAlgorithm, packageNodeFilters, packagePropertyFilters, postInstallHook);
             Runnable cleanup = new ResourceDistributionPackageCleanup(resolverFactory, resourceDistributionPackageBuilder);
             Dictionary<String, Object> props = new Hashtable<String, Object>();
             props.put(Scheduler.PROPERTY_SCHEDULER_CONCURRENT, false);
diff --git a/src/test/java/org/apache/sling/distribution/DistributionBaseIT.java b/src/test/java/org/apache/sling/distribution/DistributionBaseIT.java
index 98ba6c6..75a1603 100644
--- a/src/test/java/org/apache/sling/distribution/DistributionBaseIT.java
+++ b/src/test/java/org/apache/sling/distribution/DistributionBaseIT.java
@@ -27,7 +27,6 @@ import org.apache.sling.distribution.serialization.impl.vlt.VaultDistributionPac
 import org.apache.sling.testing.paxexam.SlingOptions;
 import org.apache.sling.testing.paxexam.TestSupport;
 import org.ops4j.pax.exam.Configuration;
-import org.ops4j.pax.exam.CoreOptions;
 import org.ops4j.pax.exam.Option;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Filter;
@@ -36,8 +35,6 @@ import org.osgi.framework.ServiceReference;
 
 import javax.inject.Inject;
 
-import java.io.File;
-
 import static org.apache.sling.testing.paxexam.SlingOptions.logback;
 import static org.apache.sling.testing.paxexam.SlingOptions.slingDistribution;
 import static org.apache.sling.testing.paxexam.SlingOptions.slingQuickstartOakTar;
diff --git a/src/main/java/org/apache/sling/distribution/packaging/package-info.java b/src/test/java/org/apache/sling/distribution/packaging/DistributionPackageInfoTest.java
similarity index 80%
copy from src/main/java/org/apache/sling/distribution/packaging/package-info.java
copy to src/test/java/org/apache/sling/distribution/packaging/DistributionPackageInfoTest.java
index 8f378be..7be009a 100644
--- a/src/main/java/org/apache/sling/distribution/packaging/package-info.java
+++ b/src/test/java/org/apache/sling/distribution/packaging/DistributionPackageInfoTest.java
@@ -17,8 +17,15 @@
  * under the License.
  */
 
-@Version("0.0.1")
 package org.apache.sling.distribution.packaging;
 
-import aQute.bnd.annotation.Version;
+import org.junit.Test;
 
+public class DistributionPackageInfoTest {
+
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalid(){
+        new DistributionPackageInfo(null);
+    }
+}
diff --git a/src/test/java/org/apache/sling/distribution/packaging/impl/FileDistributionPackageBuilderTest.java b/src/test/java/org/apache/sling/distribution/packaging/impl/FileDistributionPackageBuilderTest.java
index ea6072c..f9abb52 100644
--- a/src/test/java/org/apache/sling/distribution/packaging/impl/FileDistributionPackageBuilderTest.java
+++ b/src/test/java/org/apache/sling/distribution/packaging/impl/FileDistributionPackageBuilderTest.java
@@ -30,6 +30,7 @@ import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.distribution.DistributionRequest;
 import org.apache.sling.distribution.common.DistributionException;
 import org.apache.sling.distribution.packaging.DistributionPackage;
+import org.apache.sling.distribution.packaging.PackageInstallHook;
 import org.apache.sling.distribution.serialization.DistributionContentSerializer;
 import org.apache.sling.distribution.serialization.DistributionExportOptions;
 import org.junit.Test;
@@ -38,8 +39,9 @@ public class FileDistributionPackageBuilderTest {
 
     @Test
     public void testDefaultTempDirectory() throws DistributionException, IOException {
+        PackageInstallHook postInstallHook = new NoopPackageInstallHook();
         FileDistributionPackageBuilder builder = new FileDistributionPackageBuilder("test", new TestSerializer(), null, null, new String[0],
-                new String[0]);
+                new String[0], postInstallHook);
         DistributionPackage createdPackage = builder.createPackageForAdd(mock(ResourceResolver.class), mock(DistributionRequest.class));
 
         try {
diff --git a/src/test/java/org/apache/sling/distribution/packaging/impl/InMemoryDistributionPackageBuilderTest.java b/src/test/java/org/apache/sling/distribution/packaging/impl/InMemoryDistributionPackageBuilderTest.java
index f20dc66..b660feb 100644
--- a/src/test/java/org/apache/sling/distribution/packaging/impl/InMemoryDistributionPackageBuilderTest.java
+++ b/src/test/java/org/apache/sling/distribution/packaging/impl/InMemoryDistributionPackageBuilderTest.java
@@ -18,30 +18,97 @@
  */
 package org.apache.sling.distribution.packaging.impl;
 
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.verify;
+
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.apache.sling.api.resource.LoginException;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.distribution.DistributionRequestType;
 import org.apache.sling.distribution.SimpleDistributionRequest;
 import org.apache.sling.distribution.common.DistributionException;
 import org.apache.sling.distribution.packaging.DistributionPackage;
+import org.apache.sling.distribution.packaging.DistributionPackageInfo;
+import org.apache.sling.distribution.packaging.PackageInstallHook;
 import org.apache.sling.distribution.serialization.DistributionContentSerializer;
 import org.apache.sling.distribution.serialization.DistributionExportOptions;
+import org.apache.sling.testing.mock.sling.MockSling;
+import org.apache.sling.testing.mock.sling.ResourceResolverType;
+import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
 
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Mockito.mock;
-
+@RunWith(MockitoJUnitRunner.class)
 public class InMemoryDistributionPackageBuilderTest {
 
+    @Mock
+    private PackageInstallHook installHook;
+    
+    private ResourceResolver resolver;
+    private InMemoryDistributionPackageBuilder builder;
+    
+
+    @SuppressWarnings("deprecation")
+    @Before
+    public void before() throws LoginException {
+        resolver = MockSling.newResourceResolver(ResourceResolverType.JCR_OAK);
+        builder = new InMemoryDistributionPackageBuilder("name", new InMemDistributionContentSerializer(), new String[0], new String[0], installHook);
+    }
+
+    @Test
+    public void testReadPackage() throws Exception {
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        Map<String, Object> info = new HashMap<String, Object>();
+        info.put("test1", "value1");
+        DistributionPackageUtils.writeInfo(outputStream, info);
+        InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
+
+        DistributionPackage distPackage = builder.readPackage(resolver, inputStream);
+        DistributionPackageInfo outInfo = distPackage.getInfo();
+        assertThat(outInfo.get("test1", String.class), equalTo("value1"));
+    }
+    
+    @Test
+    public void testGetPackageInvalid() throws Exception {
+        
+    }
+    
     @Test
-    public void testCreatePackage() throws Exception {
-        InMemoryDistributionPackageBuilder builder = new InMemoryDistributionPackageBuilder("name", new InMemDistributionContentSerializer(), new String[0], new String[0]);
-        DistributionPackage pkg = builder.createPackageForAdd(mock(ResourceResolver.class), new SimpleDistributionRequest(DistributionRequestType.ADD, false, "/test"));
+    public void testGetPackageSimple() throws Exception {
+        String id = "invalid";
+        DistributionPackage distPackage = builder.getPackage(resolver, id);
+        assertThat(distPackage, nullValue());
+    }
+    
+    @Test
+    public void testInstallPackage() throws Exception {
+        SimpleDistributionRequest distributionRequest = new SimpleDistributionRequest(DistributionRequestType.ADD, false, "/test");
+        DistributionPackage pkg = builder.createPackage(resolver, distributionRequest);
         assertNotNull(pkg.createInputStream());
+        builder.installPackage(resolver, pkg);
+        verify(installHook).onPostAdd(Mockito.eq(resolver), Mockito.eq(pkg));
+    }
+    
+    @Test
+    public void testDeletePackage() throws Exception {
+        SimpleDistributionRequest distributionRequest = new SimpleDistributionRequest(DistributionRequestType.DELETE, false, "/test");
+        DistributionPackage pkg = builder.createPackage(resolver, distributionRequest);
+        builder.installPackage(resolver, pkg);
+        verify(installHook).onPreRemove(Mockito.eq(resolver), Mockito.eq(pkg));
     }
 
     private final class InMemDistributionContentSerializer implements DistributionContentSerializer {
diff --git a/src/test/java/org/apache/sling/distribution/packaging/impl/SimpleDistributionPackageTest.java b/src/test/java/org/apache/sling/distribution/packaging/impl/SimpleDistributionPackageTest.java
index 1730475..9e419bb 100644
--- a/src/test/java/org/apache/sling/distribution/packaging/impl/SimpleDistributionPackageTest.java
+++ b/src/test/java/org/apache/sling/distribution/packaging/impl/SimpleDistributionPackageTest.java
@@ -19,6 +19,8 @@
 package org.apache.sling.distribution.packaging.impl;
 
 import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.Arrays;
 
 import org.apache.commons.io.IOUtils;
@@ -27,27 +29,73 @@ import org.apache.sling.distribution.DistributionRequestType;
 import org.apache.sling.distribution.SimpleDistributionRequest;
 import org.apache.sling.distribution.packaging.impl.SimpleDistributionPackage;
 import org.junit.Test;
+import org.mockito.Mockito;
 
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.nullValue;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 /**
  * Testcase for {@link SimpleDistributionPackage}
  */
 public class SimpleDistributionPackageTest {
 
+    private static final String DSTRPCK_DELETE = "DSTRPCK:DELETE|/abc,/c";
+
+    @Test
+    public void testInvalid() {
+        String id = "invalid";
+        SimpleDistributionPackage pkg = SimpleDistributionPackage.fromIdString(id, "");
+        assertThat(pkg, nullValue());
+    }
+    
+    @Test
+    public void testInvalid2() {
+        String id = "DSTRPCK:";
+        SimpleDistributionPackage pkg = SimpleDistributionPackage.fromIdString(id, "");
+        assertThat(pkg, nullValue());
+    }
+    
+    @Test
+    public void testInvalid3() {
+        String id = "DSTRPCK:a|b|c";
+        SimpleDistributionPackage pkg = SimpleDistributionPackage.fromIdString(id, "");
+        assertThat(pkg, nullValue());
+    }
+    
+    @Test
+    public void testFromStreamError() throws IOException {
+        InputStream stream = mock(InputStream.class);
+        when(stream.read(Mockito.any(byte[].class), Mockito.eq(0), Mockito.anyInt())).thenThrow(new IOException("Expected"));
+        SimpleDistributionPackage pkg = SimpleDistributionPackage.fromStream(stream, "ADD");
+        assertThat(pkg, nullValue());
+    }
+    
     @Test
     public void testCreatedAndReadPackagesEquality() throws Exception {
-        DistributionRequest request = new SimpleDistributionRequest(DistributionRequestType.DELETE, "/abc");
+        DistributionRequest request = new SimpleDistributionRequest(DistributionRequestType.DELETE, "/abc", "/c");
         SimpleDistributionPackage createdPackage = new SimpleDistributionPackage(request, "VOID");
-        SimpleDistributionPackage readPackage = SimpleDistributionPackage.fromStream(new ByteArrayInputStream(("DSTRPCK:DELETE|/abc").getBytes()), "VOID");
+        assertThat(createdPackage.toString(), equalTo(DSTRPCK_DELETE));
+        // Just to run the code
+        createdPackage.acquire();
+        createdPackage.release();
+        createdPackage.close();
+        createdPackage.delete();
+        
+        SimpleDistributionPackage readPackage = SimpleDistributionPackage.fromStream(new ByteArrayInputStream(DSTRPCK_DELETE.getBytes()), "VOID");
         assertNotNull(readPackage);
+        assertEquals(DSTRPCK_DELETE.length(), readPackage.getSize());
         assertEquals(createdPackage.getType(), readPackage.getType());
         assertEquals(createdPackage.getInfo().getRequestType(), readPackage.getInfo().getRequestType());
         assertEquals(Arrays.toString(createdPackage.getInfo().getPaths()), Arrays.toString(readPackage.getInfo().getPaths()));
         assertEquals(createdPackage.getId(), readPackage.getId());
         assertTrue(IOUtils.contentEquals(createdPackage.createInputStream(), readPackage.createInputStream()));
+        
     }
 
     @Test
diff --git a/src/test/java/org/apache/sling/distribution/packaging/impl/importer/LocalDistributionPackageImporterTest.java b/src/test/java/org/apache/sling/distribution/packaging/impl/importer/LocalDistributionPackageImporterTest.java
index d603237..99843db 100644
--- a/src/test/java/org/apache/sling/distribution/packaging/impl/importer/LocalDistributionPackageImporterTest.java
+++ b/src/test/java/org/apache/sling/distribution/packaging/impl/importer/LocalDistributionPackageImporterTest.java
@@ -32,8 +32,10 @@ import org.apache.sling.distribution.event.impl.DistributionEventFactory;
 import org.apache.sling.distribution.packaging.DistributionPackage;
 import org.apache.sling.distribution.packaging.DistributionPackageBuilder;
 import org.apache.sling.distribution.packaging.DistributionPackageInfo;
+import org.apache.sling.distribution.packaging.PackageInstallHook;
 import org.apache.sling.distribution.packaging.impl.DistributionPackageUtils;
 import org.apache.sling.distribution.packaging.impl.FileDistributionPackageBuilder;
+import org.apache.sling.distribution.packaging.impl.NoopPackageInstallHook;
 import org.apache.sling.distribution.serialization.impl.vlt.FileVaultContentSerializer;
 import org.apache.sling.testing.mock.sling.ResourceResolverType;
 import org.apache.sling.testing.mock.sling.junit.SlingContext;
@@ -92,8 +94,9 @@ public class LocalDistributionPackageImporterTest {
                 false
         );
 
+        PackageInstallHook postInstallHook = new NoopPackageInstallHook();
         DistributionPackageBuilder builder =
-                new FileDistributionPackageBuilder(DistributionRequestType.ADD.name(), vaultSerializer, null, null, null, null);
+                new FileDistributionPackageBuilder(DistributionRequestType.ADD.name(), vaultSerializer, null, null, null, null, postInstallHook);
 
         ResourceResolver resourceResolver = slingContext.resourceResolver();
 
diff --git a/src/test/java/org/apache/sling/distribution/queue/impl/resource/ResourceQueueIT.java b/src/test/java/org/apache/sling/distribution/queue/impl/resource/ResourceQueueIT.java
index dad0fe9..552bda6 100644
--- a/src/test/java/org/apache/sling/distribution/queue/impl/resource/ResourceQueueIT.java
+++ b/src/test/java/org/apache/sling/distribution/queue/impl/resource/ResourceQueueIT.java
@@ -31,6 +31,7 @@ import org.apache.sling.distribution.queue.DistributionQueueEntry;
 import org.apache.sling.distribution.queue.DistributionQueueItem;
 import org.apache.sling.distribution.DistributionBaseIT;
 import org.apache.sling.distribution.queue.spi.DistributionQueue;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.junit.PaxExam;
@@ -48,6 +49,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+@Ignore
 @RunWith(PaxExam.class)
 public class ResourceQueueIT extends DistributionBaseIT {
 
diff --git a/src/test/resources/logback.xml b/src/test/resources/logback.xml
new file mode 100644
index 0000000..474e4ca
--- /dev/null
+++ b/src/test/resources/logback.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<configuration>
+  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%date %level [%thread] %logger{10} [%file : %line] %msg - %mdc %n</pattern>
+    </encoder>
+  </appender>
+
+  <root level="info">
+    <appender-ref ref="console"/>
+  </root>
+</configuration>