You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/10/18 23:26:54 UTC

[sling-org-apache-sling-installer-factory-packages] branch master created (now 7403415)

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

rombert pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-factory-packages.git.


      at 7403415  SLING-7167 Adjust READMEs

This branch includes the following new commits:

     new ebf980a  SLING-6082 : Add installer factory for content packages
     new 1df258b  SLING-6111 allow to configure whether to create a snapshot prior to installing a package
     new ac361f4  SLING-6176 persist error text in case of installation failures
     new c59fa80  Use parent pom 29
     new 2147d7a  Use released OSGi installer Core 3.8.0
     new e956b58  SLING-6484 for SNAPSHOT versions really reinstall every time a new package has been uploaded
     new fe01f99  use Sling Parent 30
     new a0ad33a  SLING-6484 remove workaround as FileVault 3.1.40 fixed the bug with JcrPackage.isInstalled()
     new 0263099  SLING-6987 initial support for hollow packages added
     new 27e4f50  SLING-6987 remove obsolete import package
     new 7403415  SLING-7167 Adjust READMEs

The 11 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.


-- 
To stop receiving notification emails like this one, please contact
['"commits@sling.apache.org" <co...@sling.apache.org>'].

[sling-org-apache-sling-installer-factory-packages] 04/11: Use parent pom 29

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

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-factory-packages.git

commit c59fa80573fe16771ef2493226ccf3a470043964
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Mon Oct 31 14:15:20 2016 +0000

    Use parent pom 29
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1767284 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 68139ae..b6efcd9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.apache.sling</groupId>
         <artifactId>sling</artifactId>
-        <version>28</version>
+        <version>29</version>
         <relativePath/>
     </parent>
 

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-installer-factory-packages] 07/11: use Sling Parent 30

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

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-factory-packages.git

commit fe01f9991b275a3065d9dd970ed6361176188f54
Author: Oliver Lietz <ol...@apache.org>
AuthorDate: Mon Mar 6 10:22:30 2017 +0000

    use Sling Parent 30
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1785621 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index fac9a70..8936434 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.apache.sling</groupId>
         <artifactId>sling</artifactId>
-        <version>29</version>
+        <version>30</version>
         <relativePath/>
     </parent>
 

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-installer-factory-packages] 10/11: SLING-6987 remove obsolete import package

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

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-factory-packages.git

commit 27e4f505d0a5c44bbf41ce904bc40c23a20b081e
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Fri Jun 30 14:17:43 2017 +0000

    SLING-6987 remove obsolete import package
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1800416 13f79535-47bb-0310-9956-ffa450edef68
---
 .../sling/installer/factory/packages/impl/PackageTransformer.java     | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java b/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
index 55fc0ef..f178ca5 100644
--- a/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
+++ b/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
@@ -21,10 +21,8 @@ package org.apache.sling.installer.factory.packages.impl;
 import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.text.MessageFormat;
-import java.util.Calendar;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Properties;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.zip.ZipInputStream;
@@ -32,7 +30,6 @@ import java.util.zip.ZipInputStream;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
-import org.apache.jackrabbit.util.ISO8601;
 import org.apache.jackrabbit.vault.fs.io.Archive;
 import org.apache.jackrabbit.vault.fs.io.ImportOptions;
 import org.apache.jackrabbit.vault.fs.io.ZipStreamArchive;
@@ -41,7 +38,6 @@ import org.apache.jackrabbit.vault.packaging.JcrPackage;
 import org.apache.jackrabbit.vault.packaging.JcrPackageManager;
 import org.apache.jackrabbit.vault.packaging.PackageException;
 import org.apache.jackrabbit.vault.packaging.PackageId;
-import org.apache.jackrabbit.vault.packaging.PackageProperties;
 import org.apache.jackrabbit.vault.packaging.Packaging;
 import org.apache.sling.installer.api.InstallableResource;
 import org.apache.sling.installer.api.tasks.ChangeStateTask;

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-installer-factory-packages] 08/11: SLING-6484 remove workaround as FileVault 3.1.40 fixed the bug with JcrPackage.isInstalled()

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

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-factory-packages.git

commit a0ad33a442ae9c653d08062b7787dd722c35aff4
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Thu Jun 29 13:57:05 2017 +0000

    SLING-6484 remove workaround as FileVault 3.1.40 fixed the bug with JcrPackage.isInstalled()
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1800283 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                                  |  2 +-
 .../factory/packages/impl/PackageTransformer.java        | 16 ++++++----------
 2 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/pom.xml b/pom.xml
index 8936434..699121c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -79,7 +79,7 @@
         <dependency>
             <groupId>org.apache.jackrabbit.vault</groupId>
             <artifactId>org.apache.jackrabbit.vault</artifactId>
-            <version>3.1.30</version>
+            <version>3.1.40</version>
             <scope>provided</scope>
         </dependency>
     </dependencies>
diff --git a/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java b/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
index ee49568..b3fabbf 100644
--- a/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
+++ b/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
@@ -215,16 +215,12 @@ public class PackageTransformer implements ResourceTransformer, InstallTaskFacto
                     return;
                 }
 
-                // if this is a SNAPSHOT version we always trigger a reinstall 
-                // (this workaround can be removed once https://issues.apache.org/jira/browse/JCRVLT-155 is implemented)
-                if (!pkgId.getVersionString().endsWith("-SNAPSHOT")) {
-                    // check if package was installed previously by some other means (or even by a previous run of the installer)
-                    if (pkg.isInstalled()) {
-                        String message = MessageFormat.format("Package {0} was installed externally. Marking as installed.", pkgId);
-                        logger.info(message);
-                        this.setFinishedState(ResourceState.INSTALLED, null, message);
-                        return;
-                    }
+                // check if package was installed previously by some other means (or even by a previous run of the installer)
+                if (pkg.isInstalled()) {
+                    String message = MessageFormat.format("Package {0} was installed externally. Marking as installed.", pkgId);
+                    logger.info(message);
+                    this.setFinishedState(ResourceState.INSTALLED, null, message);
+                    return;
                 }
 
                 // check if dependencies are installed

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-installer-factory-packages] 06/11: SLING-6484 for SNAPSHOT versions really reinstall every time a new package has been uploaded

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

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-factory-packages.git

commit e956b589a53b1a483f0ea9cbf2515640b633567a
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Fri Jan 27 08:36:20 2017 +0000

    SLING-6484 for SNAPSHOT versions really reinstall every time a new package has been uploaded
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1780517 13f79535-47bb-0310-9956-ffa450edef68
---
 .../factory/packages/impl/PackageTransformer.java        | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java b/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
index 550ce20..ee49568 100644
--- a/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
+++ b/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
@@ -215,12 +215,16 @@ public class PackageTransformer implements ResourceTransformer, InstallTaskFacto
                     return;
                 }
 
-                // check if package was installed in the meantime
-                if (pkg.isInstalled()) {
-                    String message = MessageFormat.format("Package {0} was installed externally. Marking as installed.", pkgId);
-                    logger.info(message);
-                    this.setFinishedState(ResourceState.INSTALLED, null, message);
-                    return;
+                // if this is a SNAPSHOT version we always trigger a reinstall 
+                // (this workaround can be removed once https://issues.apache.org/jira/browse/JCRVLT-155 is implemented)
+                if (!pkgId.getVersionString().endsWith("-SNAPSHOT")) {
+                    // check if package was installed previously by some other means (or even by a previous run of the installer)
+                    if (pkg.isInstalled()) {
+                        String message = MessageFormat.format("Package {0} was installed externally. Marking as installed.", pkgId);
+                        logger.info(message);
+                        this.setFinishedState(ResourceState.INSTALLED, null, message);
+                        return;
+                    }
                 }
 
                 // check if dependencies are installed

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-installer-factory-packages] 09/11: SLING-6987 initial support for hollow packages added

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

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-factory-packages.git

commit 02630994754015433237b6e4221132587a39a8ec
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Fri Jun 30 14:16:53 2017 +0000

    SLING-6987 initial support for hollow packages added
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1800415 13f79535-47bb-0310-9956-ffa450edef68
---
 .../factory/packages/impl/PackageTransformer.java  | 371 +++++++++++++--------
 .../impl/PackageTransformerConfiguration.java      |   4 +-
 2 files changed, 234 insertions(+), 141 deletions(-)

diff --git a/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java b/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
index b3fabbf..55fc0ef 100644
--- a/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
+++ b/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
@@ -21,19 +21,27 @@ package org.apache.sling.installer.factory.packages.impl;
 import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.text.MessageFormat;
+import java.util.Calendar;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Properties;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.zip.ZipInputStream;
 
+import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
+import org.apache.jackrabbit.util.ISO8601;
+import org.apache.jackrabbit.vault.fs.io.Archive;
 import org.apache.jackrabbit.vault.fs.io.ImportOptions;
+import org.apache.jackrabbit.vault.fs.io.ZipStreamArchive;
 import org.apache.jackrabbit.vault.packaging.Dependency;
 import org.apache.jackrabbit.vault.packaging.JcrPackage;
 import org.apache.jackrabbit.vault.packaging.JcrPackageManager;
+import org.apache.jackrabbit.vault.packaging.PackageException;
 import org.apache.jackrabbit.vault.packaging.PackageId;
+import org.apache.jackrabbit.vault.packaging.PackageProperties;
 import org.apache.jackrabbit.vault.packaging.Packaging;
 import org.apache.sling.installer.api.InstallableResource;
 import org.apache.sling.installer.api.tasks.ChangeStateTask;
@@ -52,30 +60,29 @@ import org.osgi.framework.Version;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.metatype.annotations.Designate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
-/**
- * The package transformer:
+/** The package transformer:
  * <ul>
- *   <li>detects content packages (ResourceTransformer)
- *   <li>and creates tasks for installing / removing of content packages
+ * <li>detects content packages (ResourceTransformer)
+ * <li>and creates tasks for installing / removing of content packages
  * </ul>
- */
-@Component( service = {ResourceTransformer.class, InstallTaskFactory.class})
+*/
+@Component(service = { ResourceTransformer.class, InstallTaskFactory.class })
+@Designate(ocd=PackageTransformerConfiguration.class)
 public class PackageTransformer implements ResourceTransformer, InstallTaskFactory {
 
     /** The attribute holding the package id. */
     private static final String ATTR_PCK_ID = "package-id";
 
-    /** The resource type for packages. */
-    private static final String RESOURCE_TYPE = "content-package";
+    /** The resource types for packages. */
+    private static final String RESOURCE_TYPE_REGULAR = "content-package";
+    private static final String RESOURCE_TYPE_HOLLOW = "content-package-hollow";
 
-    /**
-     * The logger.
-     */
-    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+    /** The logger. */
+    private static final Logger logger = LoggerFactory.getLogger(PackageTransformer.class);
 
     @Reference
     private SlingRepository repository;
@@ -93,9 +100,7 @@ public class PackageTransformer implements ResourceTransformer, InstallTaskFacto
         this.configuration = configuration;
     }
 
-    /**
-     * @see org.apache.sling.installer.api.tasks.ResourceTransformer#transform(org.apache.sling.installer.api.tasks.RegisteredResource)
-     */
+    /** @see org.apache.sling.installer.api.tasks.ResourceTransformer#transform(org.apache.sling.installer.api.tasks.RegisteredResource) */
     @Override
     public TransformationResult[] transform(final RegisteredResource resource) {
         if (resource.getType().equals(InstallableResource.TYPE_FILE)) {
@@ -104,11 +109,10 @@ public class PackageTransformer implements ResourceTransformer, InstallTaskFacto
         return null;
     }
 
-    /**
-     * Check if the resource is a content package
+    /** Check if the resource is a content package
+     * 
      * @param resource The resource
-     * @return {@code null} if not a content package, a result otherwise
-     */
+     * @return {@code null} if not a content package, a result otherwise */
     private TransformationResult[] checkForPackage(final RegisteredResource resource) {
         // first check if this is a zip archive
         try (final ZipInputStream zin = new ZipInputStream(new BufferedInputStream(resource.getInputStream()))) {
@@ -127,25 +131,34 @@ public class PackageTransformer implements ResourceTransformer, InstallTaskFacto
             session = repository.loginAdministrative(null);
 
             final JcrPackageManager pckMgr = pkgSvc.getPackageManager(session);
-            pck = pckMgr.upload(resource.getInputStream(), true, true);
-            if (pck.isValid()) {
-                final PackageId pid = pck.getDefinition().getId();
-                final Map<String, Object> attrs = new HashMap<String, Object>();
-                attrs.put(ATTR_PCK_ID, pid.toString());
-
-                final TransformationResult tr = new TransformationResult();
-                tr.setId(pid.getGroup() + ':' + pid.getName());
-                tr.setResourceType(RESOURCE_TYPE);
-                tr.setAttributes(attrs);
-
-                // version
-                final String version = pid.getVersionString();
-                if ( version.length() > 0 ) {
-                    tr.setVersion(new Version(cleanupVersion(version)));
+            final TransformationResult tr = new TransformationResult();
+            if (configuration.shouldCreateHollowPackages()) {
+                tr.setResourceType(RESOURCE_TYPE_HOLLOW);
+                // TODO: getting the real package id, currently this requires opening and extracting the archive (and copying files)
+                // Solved with https://issues.apache.org/jira/browse/JCRVLT-187
+                // for now we just take the filename from the URL
+                tr.setId(extractNameFromUrl(resource.getURL()));
+            } else {
+                pck = pckMgr.upload(resource.getInputStream(), true, true);
+                if (pck.isValid()) {
+                    final PackageId pid = pck.getDefinition().getId();
+                    final Map<String, Object> attrs = new HashMap<String, Object>();
+                    attrs.put(ATTR_PCK_ID, pid.toString());
+                    tr.setId(pid.getGroup() + ':' + pid.getName());
+                    tr.setResourceType(RESOURCE_TYPE_REGULAR);
+                    tr.setAttributes(attrs);
+
+                    // version
+                    final String version = pid.getVersionString();
+                    if (version.length() > 0) {
+                        tr.setVersion(new Version(cleanupVersion(version)));
+                    }
+                } else {
+                    logger.warn("Package from resource {} is invalid", resource);
+                    return null;
                 }
-
-                return new TransformationResult[] {tr};
             }
+            return new TransformationResult[] { tr };
         } catch (final Exception ioe) {
             logger.debug("Unable to check content package " + resource.getURL(), ioe);
         } finally {
@@ -160,39 +173,75 @@ public class PackageTransformer implements ResourceTransformer, InstallTaskFacto
     }
 
     /**
-     * @see org.apache.sling.installer.api.tasks.InstallTaskFactory#createTask(org.apache.sling.installer.api.tasks.TaskResourceGroup)
+     * Converts all separators to the Unix separator of forward slash.
+     *
+     * @param path  the path to be changed, null ignored
+     * @return the updated path
      */
+    private static String separatorsToUnix(String path) {
+        if (path == null || path.indexOf('\\') == -1) {
+            return path;
+        }
+        return path.replace('\\', '/');
+    }
+
+    private static String extractNameFromUrl(String url) {
+        String lastIdPart = separatorsToUnix(url);;
+        final int pos = lastIdPart.lastIndexOf('/');
+        if ( pos != -1 ) {
+            lastIdPart = lastIdPart.substring(pos + 1);
+        }
+        return lastIdPart;
+    }
+
+    /** @see org.apache.sling.installer.api.tasks.InstallTaskFactory#createTask(org.apache.sling.installer.api.tasks.TaskResourceGroup) */
     @Override
     public InstallTask createTask(final TaskResourceGroup toActivate) {
         final TaskResource resource = toActivate.getActiveResource();
-        if (resource == null || !resource.getType().equals(RESOURCE_TYPE)) {
+        if (resource == null) {
+            logger.warn("The given resource to createTask is null");
             return null;
         }
 
-        // extract the package id
-        final String id = (String)resource.getAttribute(ATTR_PCK_ID);
-        final PackageId pkgId = PackageId.fromString(id);
-        if (pkgId == null) {
-            logger.error("Error during processing of {}: Package id is wrong/null.", resource);
-            return new ChangeStateTask(toActivate, ResourceState.IGNORED);
-        }
-
-        if (resource.getState() == ResourceState.INSTALL) {
-            return new InstallPackageTask(pkgId, toActivate);
+        InstallTask task = null;
+        switch (resource.getType()) {
+        case RESOURCE_TYPE_REGULAR:
+            // extract the package id
+            final String id = (String) resource.getAttribute(ATTR_PCK_ID);
+            final PackageId pkgId = PackageId.fromString(id);
+            if (pkgId == null) {
+                logger.error("Error during processing of {}: Package id is wrong/null.", resource);
+                return new ChangeStateTask(toActivate, ResourceState.IGNORED);
+            }
+            if (resource.getState() == ResourceState.INSTALL) {
+                task = new InstallPackageTask(pkgId, toActivate);
+            } else {
+                task = new UninstallPackageTask(pkgId, toActivate);
+            }
+            break;
+        case RESOURCE_TYPE_HOLLOW:
+            if (resource.getState() == ResourceState.INSTALL) {
+                task = new InstallHollowPackageTask(toActivate);
+            } else {
+                // most probably uninstallation is not successful because this has also been installed as hollow-package!
+                logger.info("Do not uninstall {}: Hollow-Packages cannot be uninstalled.", resource);
+                return new ChangeStateTask(toActivate, ResourceState.IGNORED);
+            }
+            break;
+        default:
+            logger.error("Unupported type of {}: {}.", resource, resource.getType());
+            task = new ChangeStateTask(toActivate, ResourceState.IGNORED);
         }
-        return new UninstallPackageTask(pkgId, toActivate);
+        return task;
     }
 
-    /**
-     * Task for installing a package.
-     */
-    private class InstallPackageTask extends InstallTask {
+    private abstract class AbstractPackageInstallTask extends InstallTask {
 
-        private final PackageId pkgId;
+        protected final String name;
 
-        public InstallPackageTask(final PackageId pkgId, final TaskResourceGroup erl) {
+        public AbstractPackageInstallTask(final String name, final TaskResourceGroup erl) {
             super(erl);
-            this.pkgId = pkgId;
+            this.name = name;
         }
 
         @Override
@@ -206,8 +255,42 @@ public class PackageTransformer implements ResourceTransformer, InstallTaskFacto
                 session = repository.loginAdministrative(null);
                 final JcrPackageManager pkgMgr = pkgSvc.getPackageManager(session);
 
-                // open package
-                pkg = pkgMgr.open(pkgId);
+                doExecute(ctx, pkgMgr, resource);
+            } catch (final Exception e) {
+                String message = MessageFormat.format("Error while processing {0} content package task of {1} due to {2}, no retry.", name, resource,
+                        e.getLocalizedMessage());
+                logger.error(message, e);
+                this.setFinishedState(ResourceState.IGNORED, null, message);
+            } finally {
+                if (pkg != null) {
+                    pkg.close();
+                }
+                if (session != null) {
+                    session.logout();
+                }
+            }
+        }
+
+        protected abstract void doExecute(final InstallationContext ctx, final JcrPackageManager pkgMgr, final TaskResource resource)
+                throws RepositoryException, PackageException, IOException;
+    }
+
+    /** Task for installing a package. */
+    private class InstallPackageTask extends AbstractPackageInstallTask {
+        private final PackageId pkgId;
+        
+        public InstallPackageTask(final PackageId pkgId, final TaskResourceGroup erl) {
+            super("install", erl);
+            this.pkgId = pkgId;
+        }
+
+        @Override
+        protected void doExecute(final InstallationContext ctx, final JcrPackageManager pkgMgr, final TaskResource resource)
+                throws RepositoryException, PackageException, IOException {
+
+            // open package
+            JcrPackage pkg = pkgMgr.open(pkgId);
+            try {
                 if (pkg == null) {
                     String message = MessageFormat.format("Error during installation of {0}: Package {1} missing.", resource, pkgId);
                     logger.error(message);
@@ -241,23 +324,15 @@ public class PackageTransformer implements ResourceTransformer, InstallTaskFacto
                     ctx.log("Content package extracted: {}", resource);
                 }
 
-                
                 setFinishedState(ResourceState.INSTALLED);
 
-                // notify retry handler to install dependend packages.
+                // notify retry handler to install dependent packages.
                 retryHandler.scheduleRetry();
 
-            } catch (final Exception e) {
-                String message = MessageFormat.format("Error while processing install task of {0} due to {1}, no retry.", resource, e.getLocalizedMessage());
-                logger.error(message, e);
-                this.setFinishedState(ResourceState.IGNORED, null, message);
             } finally {
                 if (pkg != null) {
                     pkg.close();
                 }
-                if (session != null) {
-                    session.logout();
-                }
             }
         }
 
@@ -267,117 +342,133 @@ public class PackageTransformer implements ResourceTransformer, InstallTaskFacto
         }
     }
 
-    /**
-     * Task for uninstalling a package.
-     */
-    private final class UninstallPackageTask extends InstallTask {
+    private final class InstallHollowPackageTask extends AbstractPackageInstallTask {
 
-        private final PackageId pkgId;
+        public InstallHollowPackageTask(TaskResourceGroup erl) {
+            super("install-hollow", erl);
+        }
+
+        @Override
+        protected void doExecute(InstallationContext ctx, JcrPackageManager pkgMgr, TaskResource resource)
+                throws RepositoryException, PackageException, IOException {
+            Archive archive = new ZipStreamArchive(resource.getInputStream());
+            JcrPackage oldPackage = null;
+            try {
+                archive.open(false);
+                // we always have to do that, as there is no possibility to figure out whether the same package has already been installed
+                // https://issues.apache.org/jira/browse/JCRVLT-188
+                final ImportOptions opts = new ImportOptions();
+                pkgMgr.extract(archive, opts, true);
+            } finally {
+                archive.close();
+                if (oldPackage != null) {
+                    oldPackage.close();
+                }
+            }
+        }
+
+        @Override
+        public String getSortKey() {
+            return "35-" + getResource().getEntityId();
+        }
+
+    }
+
+    /** Task for uninstalling a package. */
+    private final class UninstallPackageTask extends AbstractPackageInstallTask {
+
+        private PackageId pkgId;
 
         public UninstallPackageTask(final PackageId pkgId, final TaskResourceGroup erl) {
-            super(erl);
+            super("uninstall", erl);
             this.pkgId = pkgId;
         }
 
         @Override
-        public void execute(final InstallationContext ctx) {
-            Session session = null;
-            JcrPackage pkg = null;
-            try {
-                session = repository.loginAdministrative(null);
-                final JcrPackageManager pkgMgr = pkgSvc.getPackageManager(session);
+        public String getSortKey() {
+            return "55-" + getResource().getEntityId();
+        }
 
-                pkg = pkgMgr.open(this.pkgId);
-                if ( pkg != null ) {
+        @Override
+        protected void doExecute(InstallationContext ctx, JcrPackageManager pkgMgr, TaskResource resource)
+                throws RepositoryException, PackageException, IOException {
+            JcrPackage pkg = pkgMgr.open(this.pkgId);
+            try {
+                if (pkg != null) {
                     final ImportOptions opts = new ImportOptions();
                     pkg.uninstall(opts);
                 }
-
-            } catch (final Exception e) {
-                logger.error("Error while processing uninstall task of {}.", pkgId, e);
             } finally {
                 if (pkg != null) {
                     pkg.close();
                 }
-                if (session != null) {
-                    session.logout();
-                }
             }
             ctx.log("Uninstalled content package {}", getResource());
             setFinishedState(ResourceState.UNINSTALLED);
             retryHandler.scheduleRetry();
         }
-
-        @Override
-        public String getSortKey() {
-            return "55-" + getResource().getEntityId();
-        }
     }
 
-    private static final Pattern FUZZY_VERSION = Pattern.compile( "(\\d+)(\\.(\\d+)(\\.(\\d+))?)?([^a-zA-Z0-9](.*))?",
-            Pattern.DOTALL );
+    private static final Pattern FUZZY_VERSION = Pattern.compile("(\\d+)(\\.(\\d+)(\\.(\\d+))?)?([^a-zA-Z0-9](.*))?",
+            Pattern.DOTALL);
 
-    /**
-     * Clean up version parameters. Other builders use more fuzzy definitions of
-     * the version syntax. This method cleans up such a version to match an OSGi
-     * version.
+    /** Clean up version parameters. Other builders use more fuzzy definitions of the version syntax. This method cleans up such a version
+     * to match an OSGi version.
      *
      * @param version The version string to clean up
-     * @return the clean version
-     */
+     * @return the clean version */
     private static String cleanupVersion(final String version) {
         final StringBuilder result = new StringBuilder();
-        final Matcher m = FUZZY_VERSION.matcher( version );
-        if ( m.matches() ) {
-            final String major = m.group( 1 );
-            final String minor = m.group( 3 );
-            final String micro = m.group( 5 );
-            final String qualifier = m.group( 7 );
-
-            if ( major != null ) {
-                result.append( major );
-                if ( minor != null ) {
-                    result.append( "." );
-                    result.append( minor );
-                    if ( micro != null ) {
-                        result.append( "." );
-                        result.append( micro );
-                        if ( qualifier != null ) {
-                            result.append( "." );
-                            cleanupModifier( result, qualifier );
+        final Matcher m = FUZZY_VERSION.matcher(version);
+        if (m.matches()) {
+            final String major = m.group(1);
+            final String minor = m.group(3);
+            final String micro = m.group(5);
+            final String qualifier = m.group(7);
+
+            if (major != null) {
+                result.append(major);
+                if (minor != null) {
+                    result.append(".");
+                    result.append(minor);
+                    if (micro != null) {
+                        result.append(".");
+                        result.append(micro);
+                        if (qualifier != null) {
+                            result.append(".");
+                            cleanupModifier(result, qualifier);
                         }
-                    } else if ( qualifier != null ) {
-                        result.append( ".0." );
-                        cleanupModifier( result, qualifier );
+                    } else if (qualifier != null) {
+                        result.append(".0.");
+                        cleanupModifier(result, qualifier);
                     } else {
-                        result.append( ".0" );
+                        result.append(".0");
                     }
-                } else if ( qualifier != null ) {
-                    result.append( ".0.0." );
-                    cleanupModifier( result, qualifier );
+                } else if (qualifier != null) {
+                    result.append(".0.0.");
+                    cleanupModifier(result, qualifier);
                 } else {
-                    result.append( ".0.0" );
+                    result.append(".0.0");
                 }
             }
         } else {
-            result.append( "0.0.0." );
-            cleanupModifier( result, version );
+            result.append("0.0.0.");
+            cleanupModifier(result, version);
         }
         return result.toString();
     }
 
-
-    private static void cleanupModifier( final StringBuilder result, final String modifier ) {
-        for ( int i = 0; i < modifier.length(); i++ ) {
-            char c = modifier.charAt( i );
-            if ( ( c >= '0' && c <= '9' )
-              || ( c >= 'a' && c <= 'z' )
-              || ( c >= 'A' && c <= 'Z' )
-              || c == '_'
-              || c == '-' ) {
-                result.append( c );
+    private static void cleanupModifier(final StringBuilder result, final String modifier) {
+        for (int i = 0; i < modifier.length(); i++) {
+            char c = modifier.charAt(i);
+            if ((c >= '0' && c <= '9')
+                    || (c >= 'a' && c <= 'z')
+                    || (c >= 'A' && c <= 'Z')
+                    || c == '_'
+                    || c == '-') {
+                result.append(c);
             } else {
-                result.append( '_' );
+                result.append('_');
             }
         }
     }
diff --git a/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformerConfiguration.java b/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformerConfiguration.java
index eb5689d..67fc504 100644
--- a/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformerConfiguration.java
+++ b/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformerConfiguration.java
@@ -23,6 +23,8 @@ import org.osgi.service.metatype.annotations.ObjectClassDefinition;
 
 @ObjectClassDefinition(name = "Apache Sling OSGi Installer Package Transformer", description = "Allows to configure how content packages are installed through the OSGi installer")
 public @interface PackageTransformerConfiguration {
-    @AttributeDefinition(name = "Create Snapshots", description = "Boolean flag indicating whether prior to the installation of the package a snapshot of the repository should be created.")
+    @AttributeDefinition(name = "Create Snapshots", description = "Boolean flag indicating whether prior to the installation of the package a snapshot of the repository should be created. Only relevant when hollow packages are disabled.")
     boolean shouldCreateSnapshots() default true;
+    @AttributeDefinition(name = "Use hollow packages", description = "Boolean flag indicating whether hollow packages (i.e. packages not containing actual content) should be used. This prevents the package file from being copied to the repository first before being installed (i.e. reduces required disk space, improves speed) but also prevents snapshot creation and uninstallation.")
+    boolean shouldCreateHollowPackages() default false;
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-installer-factory-packages] 11/11: SLING-7167 Adjust READMEs

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

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-factory-packages.git

commit 7403415cf12ca350d495a2e8ef6dfd6fd34b42a1
Author: Oliver Lietz <ol...@apache.org>
AuthorDate: Tue Oct 3 09:32:22 2017 +0000

    SLING-7167 Adjust READMEs
    
    add missing README
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1810757 13f79535-47bb-0310-9956-ffa450edef68
---
 README.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a8a1476
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+# Apache Sling Installer Content Package Support
+
+This module is part of the [Apache Sling](https://sling.apache.org) project.

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-installer-factory-packages] 05/11: Use released OSGi installer Core 3.8.0

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

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-factory-packages.git

commit 2147d7ab5c57be9ada7d7e505b4984207ea3b076
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Thu Nov 10 11:02:15 2016 +0000

    Use released OSGi installer Core 3.8.0
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1769083 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index b6efcd9..fac9a70 100644
--- a/pom.xml
+++ b/pom.xml
@@ -73,7 +73,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.installer.core</artifactId>
-            <version>3.7.1-SNAPSHOT</version>
+            <version>3.8.0</version>
             <scope>provided</scope>
         </dependency>
         <dependency>

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-installer-factory-packages] 03/11: SLING-6176 persist error text in case of installation failures

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

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-factory-packages.git

commit ac361f4addfe88f5057da6bd34db8a213aa2e6f0
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Fri Oct 21 09:03:23 2016 +0000

    SLING-6176 persist error text in case of installation failures
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1765962 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                                  |  2 +-
 .../factory/packages/impl/PackageTransformer.java        | 16 ++++++++++------
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/pom.xml b/pom.xml
index 5fb25fd..68139ae 100644
--- a/pom.xml
+++ b/pom.xml
@@ -73,7 +73,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.installer.core</artifactId>
-            <version>3.5.0</version>
+            <version>3.7.1-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
diff --git a/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java b/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
index 1f9ff7e..550ce20 100644
--- a/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
+++ b/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
@@ -20,6 +20,7 @@ package org.apache.sling.installer.factory.packages.impl;
 
 import java.io.BufferedInputStream;
 import java.io.IOException;
+import java.text.MessageFormat;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.regex.Matcher;
@@ -208,15 +209,17 @@ public class PackageTransformer implements ResourceTransformer, InstallTaskFacto
                 // open package
                 pkg = pkgMgr.open(pkgId);
                 if (pkg == null) {
-                    logger.error("Error during installation of {}: Package {} missing.", resource, pkgId);
-                    this.setFinishedState(ResourceState.IGNORED);
+                    String message = MessageFormat.format("Error during installation of {0}: Package {1} missing.", resource, pkgId);
+                    logger.error(message);
+                    this.setFinishedState(ResourceState.IGNORED, null, message);
                     return;
                 }
 
                 // check if package was installed in the meantime
                 if (pkg.isInstalled()) {
-                    logger.info("Package {} was installed externally. Marking as installed.", pkgId);
-                    this.setFinishedState(ResourceState.INSTALLED);
+                    String message = MessageFormat.format("Package {0} was installed externally. Marking as installed.", pkgId);
+                    logger.info(message);
+                    this.setFinishedState(ResourceState.INSTALLED, null, message);
                     return;
                 }
 
@@ -245,8 +248,9 @@ public class PackageTransformer implements ResourceTransformer, InstallTaskFacto
                 retryHandler.scheduleRetry();
 
             } catch (final Exception e) {
-                logger.error("Error while processing install task of {}.", resource, e);
-                this.setFinishedState(ResourceState.IGNORED);
+                String message = MessageFormat.format("Error while processing install task of {0} due to {1}, no retry.", resource, e.getLocalizedMessage());
+                logger.error(message, e);
+                this.setFinishedState(ResourceState.IGNORED, null, message);
             } finally {
                 if (pkg != null) {
                     pkg.close();

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-installer-factory-packages] 02/11: SLING-6111 allow to configure whether to create a snapshot prior to installing a package

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

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-factory-packages.git

commit 1df258b5f98f31181aa76c070e0fdd21acccc807
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Fri Oct 7 09:24:03 2016 +0000

    SLING-6111 allow to configure whether to create a snapshot prior to installing a package
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1763710 13f79535-47bb-0310-9956-ffa450edef68
---
 .../factory/packages/impl/PackageTransformer.java  | 19 ++++++++++++---
 .../impl/PackageTransformerConfiguration.java      | 28 ++++++++++++++++++++++
 2 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java b/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
index d46c905..1f9ff7e 100644
--- a/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
+++ b/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
@@ -48,6 +48,7 @@ import org.apache.sling.installer.api.tasks.TaskResourceGroup;
 import org.apache.sling.installer.api.tasks.TransformationResult;
 import org.apache.sling.jcr.api.SlingRepository;
 import org.osgi.framework.Version;
+import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
 import org.slf4j.Logger;
@@ -84,6 +85,13 @@ public class PackageTransformer implements ResourceTransformer, InstallTaskFacto
     @Reference
     private RetryHandler retryHandler;
 
+    private PackageTransformerConfiguration configuration;
+
+    @Activate
+    private void activate(final PackageTransformerConfiguration configuration) {
+        this.configuration = configuration;
+    }
+
     /**
      * @see org.apache.sling.installer.api.tasks.ResourceTransformer#transform(org.apache.sling.installer.api.tasks.RegisteredResource)
      */
@@ -222,10 +230,15 @@ public class PackageTransformer implements ResourceTransformer, InstallTaskFacto
 
                 // finally, install package
                 final ImportOptions opts = new ImportOptions();
+                if (configuration.shouldCreateSnapshots()) {
+                    pkg.install(opts);
+                    ctx.log("Content package installed: {}", resource);
+                } else {
+                    pkg.extract(opts);
+                    ctx.log("Content package extracted: {}", resource);
+                }
 
-                pkg.install(opts);
-
-                ctx.log("Content package installed: {}", resource);
+                
                 setFinishedState(ResourceState.INSTALLED);
 
                 // notify retry handler to install dependend packages.
diff --git a/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformerConfiguration.java b/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformerConfiguration.java
new file mode 100644
index 0000000..eb5689d
--- /dev/null
+++ b/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformerConfiguration.java
@@ -0,0 +1,28 @@
+/*
+ * 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.installer.factory.packages.impl;
+
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+
+@ObjectClassDefinition(name = "Apache Sling OSGi Installer Package Transformer", description = "Allows to configure how content packages are installed through the OSGi installer")
+public @interface PackageTransformerConfiguration {
+    @AttributeDefinition(name = "Create Snapshots", description = "Boolean flag indicating whether prior to the installation of the package a snapshot of the repository should be created.")
+    boolean shouldCreateSnapshots() default true;
+}

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-installer-factory-packages] 01/11: SLING-6082 : Add installer factory for content packages

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

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-factory-packages.git

commit ebf980aaa8c0a04a3205a4b52da639bb9488cc8a
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Fri Oct 7 08:40:29 2016 +0000

    SLING-6082 : Add installer factory for content packages
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1763696 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            |  87 +++++
 .../factory/packages/impl/PackageTransformer.java  | 367 +++++++++++++++++++++
 2 files changed, 454 insertions(+)

diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..5fb25fd
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling</artifactId>
+        <version>28</version>
+        <relativePath/>
+    </parent>
+
+    <artifactId>org.apache.sling.installer.factory.packages</artifactId>
+    <version>0.1.0-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <name>Apache Sling Installer Content Package Support</name>
+    <description> 
+        Provides support for content packages to the Apache Sling OSGi installer
+    </description>
+
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/installer/factories/packages</connection>
+        <developerConnection> scm:svn:https://svn.apache.org/repos/asf/sling/trunk/installer/factories/packages</developerConnection>
+        <url>http://svn.apache.org/viewvc/sling/trunk/installer/factories/packages</url>
+    </scm>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.jcr</groupId>
+            <artifactId>jcr</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.jcr.api</artifactId>
+            <version>2.1.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.installer.core</artifactId>
+            <version>3.5.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit.vault</groupId>
+            <artifactId>org.apache.jackrabbit.vault</artifactId>
+            <version>3.1.30</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java b/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
new file mode 100644
index 0000000..d46c905
--- /dev/null
+++ b/src/main/java/org/apache/sling/installer/factory/packages/impl/PackageTransformer.java
@@ -0,0 +1,367 @@
+/*
+ * 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.installer.factory.packages.impl;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.zip.ZipInputStream;
+
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.vault.fs.io.ImportOptions;
+import org.apache.jackrabbit.vault.packaging.Dependency;
+import org.apache.jackrabbit.vault.packaging.JcrPackage;
+import org.apache.jackrabbit.vault.packaging.JcrPackageManager;
+import org.apache.jackrabbit.vault.packaging.PackageId;
+import org.apache.jackrabbit.vault.packaging.Packaging;
+import org.apache.sling.installer.api.InstallableResource;
+import org.apache.sling.installer.api.tasks.ChangeStateTask;
+import org.apache.sling.installer.api.tasks.InstallTask;
+import org.apache.sling.installer.api.tasks.InstallTaskFactory;
+import org.apache.sling.installer.api.tasks.InstallationContext;
+import org.apache.sling.installer.api.tasks.RegisteredResource;
+import org.apache.sling.installer.api.tasks.ResourceState;
+import org.apache.sling.installer.api.tasks.ResourceTransformer;
+import org.apache.sling.installer.api.tasks.RetryHandler;
+import org.apache.sling.installer.api.tasks.TaskResource;
+import org.apache.sling.installer.api.tasks.TaskResourceGroup;
+import org.apache.sling.installer.api.tasks.TransformationResult;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.osgi.framework.Version;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * The package transformer:
+ * <ul>
+ *   <li>detects content packages (ResourceTransformer)
+ *   <li>and creates tasks for installing / removing of content packages
+ * </ul>
+ */
+@Component( service = {ResourceTransformer.class, InstallTaskFactory.class})
+public class PackageTransformer implements ResourceTransformer, InstallTaskFactory {
+
+    /** The attribute holding the package id. */
+    private static final String ATTR_PCK_ID = "package-id";
+
+    /** The resource type for packages. */
+    private static final String RESOURCE_TYPE = "content-package";
+
+    /**
+     * The logger.
+     */
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    @Reference
+    private SlingRepository repository;
+
+    @Reference
+    private Packaging pkgSvc;
+
+    @Reference
+    private RetryHandler retryHandler;
+
+    /**
+     * @see org.apache.sling.installer.api.tasks.ResourceTransformer#transform(org.apache.sling.installer.api.tasks.RegisteredResource)
+     */
+    @Override
+    public TransformationResult[] transform(final RegisteredResource resource) {
+        if (resource.getType().equals(InstallableResource.TYPE_FILE)) {
+            return checkForPackage(resource);
+        }
+        return null;
+    }
+
+    /**
+     * Check if the resource is a content package
+     * @param resource The resource
+     * @return {@code null} if not a content package, a result otherwise
+     */
+    private TransformationResult[] checkForPackage(final RegisteredResource resource) {
+        // first check if this is a zip archive
+        try (final ZipInputStream zin = new ZipInputStream(new BufferedInputStream(resource.getInputStream()))) {
+            if (zin.getNextEntry() == null) {
+                return null;
+            }
+        } catch (final IOException ioe) {
+            logger.debug("Unable to read resource.", ioe);
+            return null;
+        }
+
+        Session session = null;
+        JcrPackage pck = null;
+        try {
+            // create an admin session
+            session = repository.loginAdministrative(null);
+
+            final JcrPackageManager pckMgr = pkgSvc.getPackageManager(session);
+            pck = pckMgr.upload(resource.getInputStream(), true, true);
+            if (pck.isValid()) {
+                final PackageId pid = pck.getDefinition().getId();
+                final Map<String, Object> attrs = new HashMap<String, Object>();
+                attrs.put(ATTR_PCK_ID, pid.toString());
+
+                final TransformationResult tr = new TransformationResult();
+                tr.setId(pid.getGroup() + ':' + pid.getName());
+                tr.setResourceType(RESOURCE_TYPE);
+                tr.setAttributes(attrs);
+
+                // version
+                final String version = pid.getVersionString();
+                if ( version.length() > 0 ) {
+                    tr.setVersion(new Version(cleanupVersion(version)));
+                }
+
+                return new TransformationResult[] {tr};
+            }
+        } catch (final Exception ioe) {
+            logger.debug("Unable to check content package " + resource.getURL(), ioe);
+        } finally {
+            if (pck != null) {
+                pck.close();
+            }
+            if (session != null) {
+                session.logout();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * @see org.apache.sling.installer.api.tasks.InstallTaskFactory#createTask(org.apache.sling.installer.api.tasks.TaskResourceGroup)
+     */
+    @Override
+    public InstallTask createTask(final TaskResourceGroup toActivate) {
+        final TaskResource resource = toActivate.getActiveResource();
+        if (resource == null || !resource.getType().equals(RESOURCE_TYPE)) {
+            return null;
+        }
+
+        // extract the package id
+        final String id = (String)resource.getAttribute(ATTR_PCK_ID);
+        final PackageId pkgId = PackageId.fromString(id);
+        if (pkgId == null) {
+            logger.error("Error during processing of {}: Package id is wrong/null.", resource);
+            return new ChangeStateTask(toActivate, ResourceState.IGNORED);
+        }
+
+        if (resource.getState() == ResourceState.INSTALL) {
+            return new InstallPackageTask(pkgId, toActivate);
+        }
+        return new UninstallPackageTask(pkgId, toActivate);
+    }
+
+    /**
+     * Task for installing a package.
+     */
+    private class InstallPackageTask extends InstallTask {
+
+        private final PackageId pkgId;
+
+        public InstallPackageTask(final PackageId pkgId, final TaskResourceGroup erl) {
+            super(erl);
+            this.pkgId = pkgId;
+        }
+
+        @Override
+        public void execute(final InstallationContext ctx) {
+            final TaskResource resource = this.getResource();
+
+            // now check the dependencies
+            Session session = null;
+            JcrPackage pkg = null;
+            try {
+                session = repository.loginAdministrative(null);
+                final JcrPackageManager pkgMgr = pkgSvc.getPackageManager(session);
+
+                // open package
+                pkg = pkgMgr.open(pkgId);
+                if (pkg == null) {
+                    logger.error("Error during installation of {}: Package {} missing.", resource, pkgId);
+                    this.setFinishedState(ResourceState.IGNORED);
+                    return;
+                }
+
+                // check if package was installed in the meantime
+                if (pkg.isInstalled()) {
+                    logger.info("Package {} was installed externally. Marking as installed.", pkgId);
+                    this.setFinishedState(ResourceState.INSTALLED);
+                    return;
+                }
+
+                // check if dependencies are installed
+                for (final Dependency d : pkg.getDefinition().getDependencies()) {
+                    if (pkgMgr.resolve(d, true) == null) {
+                        logger.info("Delaying installation of {} due to missing dependency {}.", pkgId, d);
+                        return;
+                    }
+                }
+
+                // finally, install package
+                final ImportOptions opts = new ImportOptions();
+
+                pkg.install(opts);
+
+                ctx.log("Content package installed: {}", resource);
+                setFinishedState(ResourceState.INSTALLED);
+
+                // notify retry handler to install dependend packages.
+                retryHandler.scheduleRetry();
+
+            } catch (final Exception e) {
+                logger.error("Error while processing install task of {}.", resource, e);
+                this.setFinishedState(ResourceState.IGNORED);
+            } finally {
+                if (pkg != null) {
+                    pkg.close();
+                }
+                if (session != null) {
+                    session.logout();
+                }
+            }
+        }
+
+        @Override
+        public String getSortKey() {
+            return "25-" + getResource().getEntityId();
+        }
+    }
+
+    /**
+     * Task for uninstalling a package.
+     */
+    private final class UninstallPackageTask extends InstallTask {
+
+        private final PackageId pkgId;
+
+        public UninstallPackageTask(final PackageId pkgId, final TaskResourceGroup erl) {
+            super(erl);
+            this.pkgId = pkgId;
+        }
+
+        @Override
+        public void execute(final InstallationContext ctx) {
+            Session session = null;
+            JcrPackage pkg = null;
+            try {
+                session = repository.loginAdministrative(null);
+                final JcrPackageManager pkgMgr = pkgSvc.getPackageManager(session);
+
+                pkg = pkgMgr.open(this.pkgId);
+                if ( pkg != null ) {
+                    final ImportOptions opts = new ImportOptions();
+                    pkg.uninstall(opts);
+                }
+
+            } catch (final Exception e) {
+                logger.error("Error while processing uninstall task of {}.", pkgId, e);
+            } finally {
+                if (pkg != null) {
+                    pkg.close();
+                }
+                if (session != null) {
+                    session.logout();
+                }
+            }
+            ctx.log("Uninstalled content package {}", getResource());
+            setFinishedState(ResourceState.UNINSTALLED);
+            retryHandler.scheduleRetry();
+        }
+
+        @Override
+        public String getSortKey() {
+            return "55-" + getResource().getEntityId();
+        }
+    }
+
+    private static final Pattern FUZZY_VERSION = Pattern.compile( "(\\d+)(\\.(\\d+)(\\.(\\d+))?)?([^a-zA-Z0-9](.*))?",
+            Pattern.DOTALL );
+
+    /**
+     * Clean up version parameters. Other builders use more fuzzy definitions of
+     * the version syntax. This method cleans up such a version to match an OSGi
+     * version.
+     *
+     * @param version The version string to clean up
+     * @return the clean version
+     */
+    private static String cleanupVersion(final String version) {
+        final StringBuilder result = new StringBuilder();
+        final Matcher m = FUZZY_VERSION.matcher( version );
+        if ( m.matches() ) {
+            final String major = m.group( 1 );
+            final String minor = m.group( 3 );
+            final String micro = m.group( 5 );
+            final String qualifier = m.group( 7 );
+
+            if ( major != null ) {
+                result.append( major );
+                if ( minor != null ) {
+                    result.append( "." );
+                    result.append( minor );
+                    if ( micro != null ) {
+                        result.append( "." );
+                        result.append( micro );
+                        if ( qualifier != null ) {
+                            result.append( "." );
+                            cleanupModifier( result, qualifier );
+                        }
+                    } else if ( qualifier != null ) {
+                        result.append( ".0." );
+                        cleanupModifier( result, qualifier );
+                    } else {
+                        result.append( ".0" );
+                    }
+                } else if ( qualifier != null ) {
+                    result.append( ".0.0." );
+                    cleanupModifier( result, qualifier );
+                } else {
+                    result.append( ".0.0" );
+                }
+            }
+        } else {
+            result.append( "0.0.0." );
+            cleanupModifier( result, version );
+        }
+        return result.toString();
+    }
+
+
+    private static void cleanupModifier( final StringBuilder result, final String modifier ) {
+        for ( int i = 0; i < modifier.length(); i++ ) {
+            char c = modifier.charAt( i );
+            if ( ( c >= '0' && c <= '9' )
+              || ( c >= 'a' && c <= 'z' )
+              || ( c >= 'A' && c <= 'Z' )
+              || c == '_'
+              || c == '-' ) {
+                result.append( c );
+            } else {
+                result.append( '_' );
+            }
+        }
+    }
+}

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.