You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by da...@apache.org on 2018/04/27 09:59:51 UTC

[sling-org-apache-sling-feature-launcher] branch master created (now ec6b9d8)

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

davidb pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git.


      at ec6b9d8  Use felix utils ResourceBuilder and Parser instead of the ManifestParser and ManifestUtil. As with that the feature-support module is empty, remove it.

This branch includes the following new commits:

     new 80949a5  Move feature model to whiteboard git
     new 4487e24  Start changing start level handling to start order handling
     new 373e578  SLING-7512 Order features based on their dependencies.
     new f91d784  Update to parent pom 33
     new 6d459f0  Move the process package from the feature api module to the support one.
     new 0c1a241  Move resolving to separate package
     new 9e9085a  Move artifact handling to separate package
     new d19a969  Move Sling specific constants into support module
     new 3971cf3  Split feature util into io and assembly parts
     new 13bf1e6  Rename to FileUtils and use constants
     new a739692  Rename packages
     new 1ccd93e  Replace SubstVarUtil with Apache Commons Lang StrSubstitutor
     new 14bc99e  [Sling Feature Model] Split off IO packages into separate module.
     new e5c47f9  [Sling Feature Model] Refactor FeatureUtil out of the support module
     new 3699fbb  [Feature Model] Move constants from support module to feature module
     new ec6b9d8  Use felix utils ResourceBuilder and Parser instead of the ManifestParser and ManifestUtil. As with that the feature-support module is empty, remove it.

The 16 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
davidb@apache.org.

[sling-org-apache-sling-feature-launcher] 01/16: Move feature model to whiteboard git

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

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git

commit 80949a541e11f6b30298046c46c1e991a0900e8a
Author: Carsten Ziegeler <cz...@adobe.com>
AuthorDate: Fri Nov 3 15:06:50 2017 +0100

    Move feature model to whiteboard git
---
 pom.xml                                            | 128 +++++++++
 .../feature/launcher/impl/FeatureProcessor.java    | 137 +++++++++
 .../sling/feature/launcher/impl/Installation.java  | 137 +++++++++
 .../feature/launcher/impl/LauncherConfig.java      | 122 ++++++++
 .../apache/sling/feature/launcher/impl/Main.java   | 313 +++++++++++++++++++++
 .../launcher/impl/launchers/AbstractRunner.java    | 278 ++++++++++++++++++
 .../launcher/impl/launchers/FrameworkLauncher.java |  88 ++++++
 .../launcher/impl/launchers/FrameworkRunner.java   |  70 +++++
 .../sling/feature/launcher/spi/Launcher.java       |  26 ++
 .../launcher/spi/LauncherPrepareContext.java       |  32 +++
 .../feature/launcher/spi/LauncherRunContext.java   |  58 ++++
 11 files changed, 1389 insertions(+)

diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..6bf9943
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+    <!--
+        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>32</version>
+        <relativePath />
+    </parent>
+
+    <artifactId>org.apache.sling.feature.launcher</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+
+    <name>Apache Sling Feature Launcher</name>
+    <description>
+        A application launcher using Apache Sling Features
+    </description>
+
+    <properties>
+        <sling.java.version>8</sling.java.version>
+    </properties>
+
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/tooling/support/feature-launcher</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/tooling/support/feature-launcher</developerConnection>
+        <url>http://svn.apache.org/viewvc/sling/trunk/tooling/support/feature-launcher</url>
+    </scm>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                <execution>
+                    <id>unpack-dependencies</id>
+                    <phase>prepare-package</phase>
+                    <goals>
+                        <goal>unpack-dependencies</goal>
+                    </goals>
+                    <configuration>
+                        <excludes>META-INF/**</excludes>
+                        <outputDirectory>${project.build.directory}/classes</outputDirectory>
+                        <overWriteReleases>false</overWriteReleases>
+                        <overWriteSnapshots>true</overWriteSnapshots>
+                        <includeArtifactIds>org.apache.sling.feature,org.apache.sling.feature.support,org.apache.sling.commons.johnzon,org.apache.felix.converter,commons-cli,slf4j-api,slf4j-simple,osgi.core</includeArtifactIds>
+                    </configuration>
+                </execution>
+            </executions>
+            </plugin>
+                <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <mainClass>org.apache.sling.feature.launcher.impl.Main</mainClass>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.feature</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.feature.support</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.converter</artifactId>
+            <version>0.1.0-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+             <groupId>commons-cli</groupId>
+             <artifactId>commons-cli</artifactId>
+             <version>1.3.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.johnzon</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>2.8.9</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
new file mode 100644
index 0000000..14eaf9c
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
@@ -0,0 +1,137 @@
+/*
+ * 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.feature.launcher.impl;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sling.feature.Application;
+import org.apache.sling.feature.Artifact;
+import org.apache.sling.feature.Configuration;
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.ExtensionType;
+import org.apache.sling.feature.launcher.impl.LauncherConfig.StartupMode;
+import org.apache.sling.feature.support.ArtifactHandler;
+import org.apache.sling.feature.support.ArtifactManager;
+import org.apache.sling.feature.support.FeatureUtil;
+import org.apache.sling.feature.support.json.ApplicationJSONReader;
+import org.apache.sling.feature.support.json.ApplicationJSONWriter;
+
+public class FeatureProcessor {
+
+    /**
+     * Initialize the launcher
+     * Read the features and prepare the application
+     * @param config The current configuration
+     * @param artifactManager The artifact manager
+     */
+    public static Application createApplication(final LauncherConfig config,
+            final ArtifactManager artifactManager)
+    throws IOException {
+        final Application app;
+        if ( config.getApplicationFile() != null ) {
+            String absoluteArg = config.getApplicationFile();
+            if ( absoluteArg.indexOf(":") < 2 ) {
+                absoluteArg = new File(absoluteArg).getAbsolutePath();
+            }
+            final ArtifactHandler appArtifact = artifactManager.getArtifactHandler(absoluteArg);
+
+            try (final FileReader r = new FileReader(appArtifact.getFile())) {
+                app = ApplicationJSONReader.read(r);
+            }
+
+        } else {
+           app = FeatureUtil.assembleApplication(null, artifactManager, FeatureUtil.getFeatureFiles(config.getHomeDirectory(), config.getFeatureFiles()).toArray(new String[0]));
+        }
+
+        // write application back
+        final File file = new File(config.getHomeDirectory(), "resources" + File.separatorChar + "provisioning" + File.separatorChar + "application.json");
+        file.getParentFile().mkdirs();
+
+        try (final FileWriter writer = new FileWriter(file)) {
+            ApplicationJSONWriter.write(writer, app);
+        } catch ( final IOException ioe) {
+            Main.LOG().error("Error while writing application file: {}", ioe.getMessage(), ioe);
+            System.exit(1);
+        }
+
+        return app;
+    }
+
+    /**
+     * Prepare the launcher
+     * - add all bundles to the bundle map of the installation object
+     * - add all other artifacts to the install directory (only if startup mode is INSTALL)
+     * - process configurations
+     */
+    public static void prepareLauncher(final LauncherConfig config,
+            final ArtifactManager artifactManager,
+            final Application app) throws Exception {
+        for(final Map.Entry<Integer, List<Artifact>> entry : app.getBundles().getBundlesByStartLevel().entrySet()) {
+            for(final Artifact a : entry.getValue()) {
+                final ArtifactHandler handler = artifactManager.getArtifactHandler(":" + a.getId().toMvnPath());
+                final File artifactFile = handler.getFile();
+
+                config.getInstallation().addBundle(entry.getKey(), artifactFile);
+            }
+        }
+        int index = 1;
+        for(final Extension ext : app.getExtensions()) {
+            if ( ext.getType() == ExtensionType.ARTIFACTS ) {
+                for(final Artifact a : ext.getArtifacts() ) {
+                    if ( config.getStartupMode() == StartupMode.PURE ) {
+                        throw new Exception("Artifacts other than bundle are not supported by framework launcher.");
+                    }
+                    final ArtifactHandler handler = artifactManager.getArtifactHandler(":" + a.getId().toMvnPath());
+                    config.getInstallation().addInstallableArtifact(handler.getFile());
+                }
+            } else {
+                if ( ext.getName().equals(Extension.NAME_REPOINIT) ) {
+                    if ( ext.getType() != ExtensionType.TEXT ) {
+                        throw new Exception(Extension.NAME_REPOINIT + " extension must be of type text and not json");
+                    }
+                    final Configuration cfg = new Configuration("org.apache.sling.jcr.repoinit.RepositoryInitializer", "repoinit" + String.valueOf(index));
+                    index++;
+                    cfg.getProperties().put("scripts", ext.getText());
+                    config.getInstallation().addConfiguration(cfg.getName(), cfg.getFactoryPid(), cfg.getProperties());
+                } else {
+                    if ( ext.isRequired() ) {
+                        throw new Exception("Unknown required extension " + ext.getName());
+                    }
+                }
+            }
+        }
+
+        for(final Configuration cfg : app.getConfigurations()) {
+            if ( cfg.isFactoryConfiguration() ) {
+                config.getInstallation().addConfiguration(cfg.getName(), cfg.getFactoryPid(), cfg.getProperties());
+            } else {
+                config.getInstallation().addConfiguration(cfg.getPid(), null, cfg.getProperties());
+            }
+        }
+
+        for(final Map.Entry<String, String> prop : app.getFrameworkProperties()) {
+            if ( !config.getInstallation().getFrameworkProperties().containsKey(prop.getKey()) ) {
+                config.getInstallation().getFrameworkProperties().put(prop.getKey(), prop.getValue());
+            }
+        }
+    }
+}
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/Installation.java b/src/main/java/org/apache/sling/feature/launcher/impl/Installation.java
new file mode 100644
index 0000000..2dff508
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/Installation.java
@@ -0,0 +1,137 @@
+/*
+ * 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.feature.launcher.impl;
+
+import org.apache.sling.feature.launcher.spi.LauncherRunContext;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class holds the configuration of the launcher.
+ */
+public class Installation implements LauncherRunContext {
+
+    /** The map with the framework properties. */
+    private final Map<String, String> fwkProperties = new HashMap<>();
+
+    /** Bundle map */
+    private final Map<Integer, List<File>> bundleMap = new HashMap<>();
+
+    /** Artifacts to be installed */
+    private final List<File> installables = new ArrayList<>();
+
+    /** Configurations, they are installed on first start. */
+    private final List<Object[]> configurations = new ArrayList<>();
+
+    /** The list of app jars. */
+    private final List<File> appJars = new ArrayList<>();
+
+    /**
+     * Add an application jar.
+     * @param jar The application jar
+     */
+    public void addAppJar(final File jar) {
+        this.appJars.add(jar);
+    }
+
+    /**
+     * Get the list of application jars.
+     * @return The list of app jars
+     */
+    public List<File> getAppJars() {
+        return this.appJars;
+    }
+
+    /**
+     * Add a bundle with the given start level
+     * @param startLevel The start level
+     * @param file The bundle file
+     */
+    public void addBundle(final Integer startLevel, final File file) {
+        List<File> files = bundleMap.get(startLevel);
+        if ( files == null ) {
+            files = new ArrayList<>();
+            bundleMap.put(startLevel, files);
+        }
+        files.add(file);
+    }
+
+    /**
+     * Add an artifact to be installed by the installer
+     * @param file The file
+     */
+    public void addInstallableArtifact(final File file) {
+        this.installables.add(file);
+    }
+
+    /**
+     * Add a configuration
+     * @param pid The pid
+     * @param factoryPid The factory pid
+     * @param properties The propertis
+     */
+    public void addConfiguration(final String pid, final String factoryPid, final Dictionary<String, Object> properties) {
+        this.configurations.add(new Object[] {pid, factoryPid, properties});
+    }
+
+    /**
+     * @see org.apache.sling.feature.launcher.spi.LauncherRunContext#getFrameworkProperties()
+     */
+    @Override
+    public Map<String, String> getFrameworkProperties() {
+        return this.fwkProperties;
+    }
+
+    /**
+     * @see org.apache.sling.feature.launcher.spi.LauncherRunContext#getBundleMap()
+     */
+    @Override
+    public Map<Integer, List<File>> getBundleMap() {
+        return this.bundleMap;
+    }
+
+    /**
+     * @see org.apache.sling.feature.launcher.spi.LauncherRunContext#getConfigurations()
+     */
+    @Override
+    public List<Object[]> getConfigurations() {
+        return this.configurations;
+    }
+
+    /**
+     * @see org.apache.sling.feature.launcher.spi.LauncherRunContext#getInstallableArtifacts()
+     */
+    @Override
+    public List<File> getInstallableArtifacts() {
+        return this.installables;
+    }
+
+    /**
+     * Clear all in-memory objects
+     */
+    public void clear() {
+        this.configurations.clear();
+        this.fwkProperties.clear();
+        this.bundleMap.clear();
+        this.installables.clear();
+    }
+}
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java b/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
new file mode 100644
index 0000000..56095b9
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
@@ -0,0 +1,122 @@
+/*
+ * 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.feature.launcher.impl;
+
+import org.apache.sling.feature.support.ArtifactManagerConfig;
+import org.apache.sling.feature.support.spi.ArtifactProviderContext;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * This class holds the configuration of the launcher.
+ */
+public class LauncherConfig
+    extends ArtifactManagerConfig
+    implements ArtifactProviderContext {
+
+    public enum StartupMode {
+        INSTALLER,
+        PURE
+    };
+
+    private static final String HOME = "launcher";
+
+    private static final String CACHE_DIR = "cache";
+
+    /** The feature files or directories. */
+    private volatile String[] featureFiles;
+
+    /** The application file. */
+    private volatile String appFile;
+
+    private volatile StartupMode startupMode = StartupMode.PURE;
+
+    private final Installation installation = new Installation();
+
+    /**
+     * Create a new configuration object.
+     * Set the default values
+     */
+    public LauncherConfig() {
+        this.setCacheDirectory(new File(getHomeDirectory(), CACHE_DIR));
+    }
+
+    public void setApplicationFile(final String value) {
+        appFile = value;
+    }
+
+    public String getApplicationFile() {
+        return this.appFile;
+    }
+
+    /**
+     * Set the list of feature files or directories.
+     * @param value The array with the feature file names.
+     */
+    public void setFeatureFiles(final String[] value) {
+        this.featureFiles = value;
+        if ( value != null && value.length == 0 ) {
+            this.featureFiles = null;
+        }
+    }
+
+    /**
+     * Get the list of feature files.
+     * @return The array of names.
+     * @throws IOException
+     */
+    public String[] getFeatureFiles() {
+        return this.featureFiles;
+    }
+
+
+    /**
+     * Get the home directory.
+     * @return The home directory.
+     */
+    public File getHomeDirectory() {
+        return new File(HOME);
+    }
+
+    /**
+     * Get the startup mode.
+     *
+     * @return The current startup mode.
+     */
+    public StartupMode getStartupMode() {
+        return this.startupMode;
+    }
+
+    /**
+     * Sets the startup mode to {@link StartupMode#INSTALLER}.
+     */
+    public void setUseInstaller() {
+        this.startupMode = StartupMode.INSTALLER;
+    }
+
+    public Installation getInstallation() {
+        return this.installation;
+    }
+
+    /**
+     * Clear all in-memory objects
+     */
+    public void clear() {
+        this.installation.clear();
+    }
+}
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/Main.java b/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
new file mode 100644
index 0000000..31050fe
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
@@ -0,0 +1,313 @@
+/*
+ * 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.feature.launcher.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.cli.BasicParser;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.sling.feature.Application;
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.launcher.impl.launchers.FrameworkLauncher;
+import org.apache.sling.feature.launcher.spi.Launcher;
+import org.apache.sling.feature.launcher.spi.LauncherPrepareContext;
+import org.apache.sling.feature.support.ArtifactHandler;
+import org.apache.sling.feature.support.ArtifactManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This is the launcher main class.
+ * It parses command line parameters and prepares the launcher.
+ */
+public class Main {
+
+    private static Logger LOGGER;
+
+    public static Logger LOG() {
+        if ( LOGGER == null ) {
+            LOGGER = LoggerFactory.getLogger("launcher");
+        }
+        return LOGGER;
+    }
+
+    /** Split a string into key and value */
+    private static String[] split(final String val) {
+        final int pos = val.indexOf('=');
+        if ( pos == -1 ) {
+            return new String[] {val, "true"};
+        }
+        return new String[] {val.substring(0, pos), val.substring(pos + 1)};
+    }
+
+    /**
+     * Parse the command line parameters and update a configuration object.
+     * @param args Command line parameters
+     * @return Configuration object.
+     */
+    private static void parseArgs(final LauncherConfig config, final String[] args) {
+        Main.LOG().info("Assembling configuration...");
+        final Options options = new Options();
+
+        final Option repoOption =  new Option("u", true, "Set repository url");
+        final Option modelOption =  new Option("f", true, "Set feature files/directories");
+        final Option appOption =  new Option("a", true, "Set application file");
+        final Option fwkProperties = new Option("D", true, "Set framework properties");
+        fwkProperties.setArgs(20);
+        final Option debugOption = new Option("v", true, "Verbose");
+        debugOption.setArgs(0);
+        final Option installerOption = new Option("I", true, "Use OSGi installer for additional artifacts.");
+        installerOption.setArgs(0);
+        options.addOption(repoOption);
+        options.addOption(appOption);
+        options.addOption(modelOption);
+        options.addOption(fwkProperties);
+        options.addOption(debugOption);
+        options.addOption(installerOption);
+
+        final CommandLineParser clp = new BasicParser();
+        try {
+            final CommandLine cl = clp.parse(options, args);
+
+            if ( cl.hasOption(repoOption.getOpt()) ) {
+                final String value = cl.getOptionValue(repoOption.getOpt());
+                config.setRepositoryUrls(value.split(","));
+            }
+            if ( cl.hasOption(modelOption.getOpt()) ) {
+                final String value = cl.getOptionValue(modelOption.getOpt());
+                config.setFeatureFiles(value.split(","));
+            }
+            if ( cl.hasOption(fwkProperties.getOpt()) ) {
+                for(final String value : cl.getOptionValues(fwkProperties.getOpt())) {
+                    final String[] keyVal = split(value);
+
+                    config.getInstallation().getFrameworkProperties().put(keyVal[0], keyVal[1]);
+                }
+            }
+            if ( cl.hasOption(debugOption.getOpt()) ) {
+                System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "debug");
+                LOGGER = null;
+            }
+            if ( cl.hasOption(installerOption.getOpt()) ) {
+                config.setUseInstaller();
+            }
+            if ( cl.hasOption(appOption.getOpt()) ) {
+                config.setApplicationFile(cl.getOptionValue(appOption.getOpt()));
+            }
+        } catch ( final ParseException pe) {
+            Main.LOG().error("Unable to parse command line: {}", pe.getMessage(), pe);
+            System.exit(1);
+        }
+    }
+
+    public static void main(final String[] args) {
+        // setup logging
+        System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "info");
+        System.setProperty("org.slf4j.simpleLogger.showThreadName", "false");
+        System.setProperty("org.slf4j.simpleLogger.levelInBrackets", "true");
+        System.setProperty("org.slf4j.simpleLogger.showLogName", "false");
+        Main.LOG().info("");
+        Main.LOG().info("Apache Sling Application Launcher");
+        Main.LOG().info("---------------------------------");
+
+        // check if launcher has already been created
+        final LauncherConfig launcherConfig = new LauncherConfig();
+        parseArgs(launcherConfig, args);
+
+        ArtifactManager artifactManager = null;
+        try {
+
+            Main.LOG().info("Initializing...");
+            try {
+                artifactManager = ArtifactManager.getArtifactManager(launcherConfig);
+            } catch ( final IOException ioe) {
+                Main.LOG().error("Unable to setup artifact manager: {}", ioe.getMessage(), ioe);
+                System.exit(1);
+            }
+            Main.LOG().info("Artifact Repositories: {}", Arrays.toString(launcherConfig.getRepositoryUrls()));
+            Main.LOG().info("Assembling provisioning model...");
+
+            try {
+                final Launcher launcher = new FrameworkLauncher();
+                final Application app = FeatureProcessor.createApplication(launcherConfig, artifactManager);
+
+                Main.LOG().info("");
+                Main.LOG().info("Assembling launcher...");
+                final ArtifactManager aMgr = artifactManager;
+                final LauncherPrepareContext ctx = new LauncherPrepareContext() {
+
+                    @Override
+                    public File getArtifactFile(final ArtifactId artifact) throws IOException {
+                        final ArtifactHandler handler = aMgr.getArtifactHandler(":" + artifact.toMvnPath());
+                        return handler.getFile();
+                    }
+
+                    @Override
+                    public void addAppJar(final File jar) {
+                        launcherConfig.getInstallation().addAppJar(jar);
+                    }
+                };
+                launcher.prepare(ctx, app);
+
+                FeatureProcessor.prepareLauncher(launcherConfig, artifactManager, app);
+
+            } catch ( final Exception iae) {
+                Main.LOG().error("Error while assembling launcher: {}", iae.getMessage(), iae);
+                System.exit(1);
+            }
+
+            Main.LOG().info("Using {} local artifacts, {} cached artifacts, and {} downloaded artifacts",
+                    launcherConfig.getLocalArtifacts(), launcherConfig.getCachedArtifacts(), launcherConfig.getDownloadedArtifacts());
+        } finally {
+            if ( artifactManager != null ) {
+                artifactManager.shutdown();
+            }
+        }
+
+        try {
+            run(launcherConfig);
+        } catch ( final Exception iae) {
+            Main.LOG().error("Error while running launcher: {}", iae.getMessage(), iae);
+            System.exit(1);
+        }
+    }
+
+    private static final String STORAGE_PROPERTY = "org.osgi.framework.storage";
+
+    private static final String START_LEVEL_PROP = "org.osgi.framework.startlevel.beginning";
+
+    /**
+     * Run launcher.
+     * @param config The configuration
+     * @throws Exception If anything goes wrong
+     */
+    private static void run(final LauncherConfig config) throws Exception {
+        Main.LOG().info("");
+        Main.LOG().info("Starting launcher...");
+        Main.LOG().info("Launcher Home: {}", config.getHomeDirectory().getAbsolutePath());
+        Main.LOG().info("Cache Directory: {}", config.getCacheDirectory().getAbsolutePath());
+        Main.LOG().info("Startup Mode: {}", config.getStartupMode());
+        Main.LOG().info("");
+
+        final Installation installation = config.getInstallation();
+
+        // set sling home, and use separate locations for launchpad and properties
+        installation.getFrameworkProperties().put("sling.home", config.getHomeDirectory().getAbsolutePath());
+        installation.getFrameworkProperties().put("sling.launchpad", config.getHomeDirectory().getAbsolutePath() + "/launchpad");
+        installation.getFrameworkProperties().put("sling.properties", "conf/sling.properties");
+
+
+        // additional OSGi properties
+        // move storage inside launcher
+        if ( installation.getFrameworkProperties().get(STORAGE_PROPERTY) == null ) {
+            installation.getFrameworkProperties().put(STORAGE_PROPERTY, config.getHomeDirectory().getAbsolutePath() + File.separatorChar + "framework");
+        }
+        // set start level to 30
+        if ( installation.getFrameworkProperties().get(START_LEVEL_PROP) == null ) {
+            installation.getFrameworkProperties().put(START_LEVEL_PROP, "30");
+        }
+
+        final Launcher launcher = new FrameworkLauncher();
+        launcher.run(installation, createClassLoader(installation));
+
+        config.clear();
+    }
+
+    /**
+     * Create the class loader.
+     * @param installation The launcher configuration
+     * @throws Exception If anything goes wrong
+     */
+    public static ClassLoader createClassLoader(final Installation installation) throws Exception {
+        final List<URL> list = new ArrayList<>();
+        for(final File f : installation.getAppJars()) {
+            try {
+                list.add(f.toURI().toURL());
+            } catch (IOException e) {
+                // ignore
+            }
+        }
+        list.add(Main.class.getProtectionDomain().getCodeSource().getLocation());
+
+        final URL[] urls = list.toArray(new URL[list.size()]);
+
+        if ( Main.LOG().isDebugEnabled() ) {
+            Main.LOG().debug("App classpath: ");
+            for (int i = 0; i < urls.length; i++) {
+                Main.LOG().debug(" - {}", urls[i]);
+            }
+        }
+
+        // create a paranoid class loader, loading from parent last
+        final ClassLoader cl = new URLClassLoader(urls) {
+            @Override
+            public final Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+                // First check if it's already loaded
+                Class<?> clazz = findLoadedClass(name);
+
+                if (clazz == null) {
+
+                    try {
+                        clazz = findClass(name);
+                    } catch (ClassNotFoundException cnfe) {
+                        ClassLoader parent = getParent();
+                        if (parent != null) {
+                            // Ask to parent ClassLoader (can also throw a CNFE).
+                            clazz = parent.loadClass(name);
+                        } else {
+                            // Propagate exception
+                            throw cnfe;
+                        }
+                    }
+                }
+
+                if (resolve) {
+                    resolveClass(clazz);
+                }
+
+                return clazz;
+            }
+
+            @Override
+            public final URL getResource(final String name) {
+
+                URL resource = findResource(name);
+                ClassLoader parent = this.getParent();
+                if (resource == null && parent != null) {
+                    resource = parent.getResource(name);
+                }
+
+                return resource;
+            }
+        };
+
+        Thread.currentThread().setContextClassLoader(cl);
+
+        return cl;
+    }
+}
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/launchers/AbstractRunner.java b/src/main/java/org/apache/sling/feature/launcher/impl/launchers/AbstractRunner.java
new file mode 100644
index 0000000..0be1804
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/launchers/AbstractRunner.java
@@ -0,0 +1,278 @@
+/*
+ * 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.feature.launcher.impl.launchers;
+
+import org.apache.sling.feature.launcher.impl.Main;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.startlevel.BundleStartLevel;
+import org.osgi.framework.wiring.FrameworkWiring;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Common functionality for the framework start.
+ */
+public class AbstractRunner {
+
+    private volatile ServiceTracker<Object, Object> configAdminTracker;
+
+    private volatile ServiceTracker<Object, Object> installerTracker;
+
+    private final List<Object[]> configurations;
+
+    private final List<File> installables;
+
+    public AbstractRunner(final List<Object[]> configurations, final List<File> installables) {
+        this.configurations = new ArrayList<>(configurations);
+        this.installables = installables;
+    }
+
+    protected void setupFramework(final Framework framework, final Map<Integer, List<File>> bundlesMap)
+    throws BundleException {
+        if ( !configurations.isEmpty() ) {
+            this.configAdminTracker = new ServiceTracker<>(framework.getBundleContext(),
+                    "org.osgi.service.cm.ConfigurationAdmin",
+                    new ServiceTrackerCustomizer<Object, Object>() {
+
+                        @Override
+                        public Object addingService(final ServiceReference<Object> reference) {
+                            // get config admin
+                            final Object cm = framework.getBundleContext().getService(reference);
+                            if ( cm != null ) {
+                                try {
+                                    configure(cm);
+                                } finally {
+                                    framework.getBundleContext().ungetService(reference);
+                                }
+                            }
+                            return null;
+                        }
+
+                        @Override
+                        public void modifiedService(ServiceReference<Object> reference, Object service) {
+                            // nothing to do
+                        }
+
+                        @Override
+                        public void removedService(ServiceReference<Object> reference, Object service) {
+                            // nothing to do
+                        }
+            });
+            this.configAdminTracker.open();
+        }
+        if ( installables != null && !installables.isEmpty() ) {
+            this.installerTracker = new ServiceTracker<>(framework.getBundleContext(),
+                    "org.apache.sling.installer.api.OsgiInstaller",
+                    new ServiceTrackerCustomizer<Object, Object>() {
+
+                        @Override
+                        public Object addingService(final ServiceReference<Object> reference) {
+                            // get installer
+                            final Object installer = framework.getBundleContext().getService(reference);
+                            if ( installer != null ) {
+                                try {
+                                    install(installer);
+                                } finally {
+                                    framework.getBundleContext().ungetService(reference);
+                                }
+                            }
+                            return null;
+                        }
+
+                        @Override
+                        public void modifiedService(ServiceReference<Object> reference, Object service) {
+                            // nothing to do
+                        }
+
+                        @Override
+                        public void removedService(ServiceReference<Object> reference, Object service) {
+                            // nothing to do
+                        }
+            });
+            this.installerTracker.open();
+        }
+        try {
+            this.install(framework, bundlesMap);
+        } catch ( final IOException ioe) {
+            throw new BundleException("Unable to install bundles.", ioe);
+        }
+    }
+
+    private void configure(final Object configAdmin) {
+        try {
+            final Method createConfig = configAdmin.getClass().getDeclaredMethod("getConfiguration", String.class, String.class);
+            final Method createFactoryConfig = configAdmin.getClass().getDeclaredMethod("getFactoryConfiguration", String.class, String.class, String.class);
+
+            Method updateMethod = null;
+            for(final Object[] obj : this.configurations) {
+                final Object cfg;
+                if ( obj[1] != null ) {
+                    cfg = createFactoryConfig.invoke(configAdmin, obj[1], obj[0], null);
+                } else {
+                    cfg = createConfig.invoke(configAdmin, obj[0], null);
+                }
+                if ( updateMethod == null ) {
+                    updateMethod = cfg.getClass().getDeclaredMethod("update", Dictionary.class);
+                }
+                updateMethod.invoke(cfg, obj[2]);
+            }
+        } catch ( final Exception e) {
+            Main.LOG().error("Unable to create configurations", e);
+            throw new RuntimeException(e);
+        }
+        final Thread t = new Thread(() -> { configAdminTracker.close(); configAdminTracker = null; });
+        t.setDaemon(false);
+        t.start();
+        this.configurations.clear();
+    }
+
+    private boolean isSystemBundleFragment(final Bundle installedBundle) {
+        final String fragmentHeader = getFragmentHostHeader(installedBundle);
+        return fragmentHeader != null
+            && fragmentHeader.indexOf(Constants.EXTENSION_DIRECTIVE) > 0;
+    }
+
+    /**
+     * Gets the bundle's Fragment-Host header.
+     */
+    private String getFragmentHostHeader(final Bundle b) {
+        return b.getHeaders().get( Constants.FRAGMENT_HOST );
+    }
+
+    /**
+     * Install the bundles
+     * @param bundleMap The map with the bundles indexed by start level
+     * @throws IOException, BundleException If anything goes wrong.
+     */
+    private void install(final Framework framework, final Map<Integer, List<File>> bundleMap)
+    throws IOException, BundleException {
+        final BundleContext bc = framework.getBundleContext();
+        int defaultStartLevel = getProperty(bc, "felix.startlevel.bundle", 1);
+        for(final Integer startLevel : sortStartLevels(bundleMap.keySet(), defaultStartLevel)) {
+            Main.LOG().debug("Installing bundles with start level {}", startLevel);
+
+            for(final File file : bundleMap.get(startLevel)) {
+                Main.LOG().debug("- {}", file.getName());
+
+                // use reference protocol. This avoids copying the binary to the cache directory
+                // of the framework
+                final Bundle bundle = bc.installBundle("reference:" + file.toURI().toURL(), null);
+                if ( startLevel > 0 ) {
+                    bundle.adapt(BundleStartLevel.class).setStartLevel(startLevel);
+                }
+
+                // fragment?
+                if ( !isSystemBundleFragment(bundle) ) {
+                    final String fragmentHostHeader = getFragmentHostHeader(bundle);
+                    if (fragmentHostHeader != null) {
+                        for (final Bundle b : bc.getBundles()) {
+                            if (fragmentHostHeader.equals(b.getSymbolicName())) {
+                                final FrameworkWiring fw = framework.adapt(FrameworkWiring.class);
+                                fw.refreshBundles(Collections.singleton(b));
+                                break;
+                            }
+                        }
+
+                    } else {
+                        bundle.start();
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Sort the start levels in the ascending order. The only exception is the start level
+     * "0", which should be put at the position configured in {@code felix.startlevel.bundle}.
+     *
+     * @param startLevels integer start levels
+     * @return sorted start levels
+     */
+    private static Iterable<Integer> sortStartLevels(final Collection<Integer> startLevels, final int defaultStartLevel) {
+        final List<Integer> result = new ArrayList<>(startLevels);
+        Collections.sort(result, (o1, o2) -> {
+            int i1 = o1 == 0 ? defaultStartLevel : o1;
+            int i2 = o2 == 0 ? defaultStartLevel : o2;
+            return Integer.compare(i1, i2);
+        });
+        return result;
+    }
+
+    private static int getProperty(BundleContext bc, String propName, int defaultValue) {
+        String val = bc.getProperty(propName);
+        if (val == null) {
+            return defaultValue;
+        } else {
+            return Integer.parseInt(val);
+        }
+    }
+
+    private void install(final Object installer) {
+        try {
+            final Class<?> installableResourceClass = installer.getClass().getClassLoader().loadClass("org.apache.sling.installer.api.InstallableResource");
+            final Object resources = Array.newInstance(installableResourceClass, this.installables.size());
+            final Method registerResources = installer.getClass().getDeclaredMethod("registerResources", String.class, resources.getClass());
+            final Constructor<?> constructor = installableResourceClass.getDeclaredConstructor(String.class,
+                    InputStream.class,
+                    Dictionary.class,
+                    String.class,
+                    String.class,
+                    Integer.class);
+
+            for(int i=0; i<this.installables.size();i++) {
+                final File f = this.installables.get(i);
+                final Dictionary<String, Object> dict = new Hashtable<>();
+                dict.put("resource.uri.hint", f.toURI().toString());
+                final Object rsrc = constructor.newInstance(f.getAbsolutePath(),
+                        new FileInputStream(f),
+                        dict,
+                        f.getName(),
+                        "file",
+                        null);
+                Array.set(resources, i, rsrc);
+            }
+            registerResources.invoke(installer, "cloudlauncher", resources);
+        } catch ( final Exception e) {
+            Main.LOG().error("Unable to contact installer and install additional artifacts", e);
+            throw new RuntimeException(e);
+        }
+        final Thread t = new Thread(() -> { installerTracker.close(); installerTracker = null; });
+        t.setDaemon(false);
+        t.start();
+        this.installables.clear();
+    }
+}
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java b/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java
new file mode 100644
index 0000000..8bb5fdc
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java
@@ -0,0 +1,88 @@
+/*
+ * 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.feature.launcher.impl.launchers;
+
+import org.apache.sling.feature.Application;
+import org.apache.sling.feature.launcher.impl.Main;
+import org.apache.sling.feature.launcher.spi.Launcher;
+import org.apache.sling.feature.launcher.spi.LauncherPrepareContext;
+import org.apache.sling.feature.launcher.spi.LauncherRunContext;
+import org.apache.sling.feature.support.util.SubstVarUtil;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Launcher directly using the OSGi launcher API.
+ */
+public class FrameworkLauncher implements Launcher {
+
+
+    @Override
+    public void prepare(final LauncherPrepareContext context, final Application app) throws Exception {
+        context.addAppJar(context.getArtifactFile(app.getFramework()));
+    }
+
+    /**
+     * Run the launcher
+     * @throws If anything goes wrong
+     */
+    @Override
+    public void run(final LauncherRunContext context, final ClassLoader cl) throws Exception {
+        Map<String, String> properties = new HashMap<>();
+        context.getFrameworkProperties().forEach((key, value) -> {
+            properties.put(key, SubstVarUtil.substVars(value, key,null, context.getFrameworkProperties()));
+        });
+        if ( Main.LOG().isDebugEnabled() ) {
+            Main.LOG().debug("Bundles:");
+            for(final Integer key : context.getBundleMap().keySet()) {
+                Main.LOG().debug("-- Start Level {}", key);
+                for(final File f : context.getBundleMap().get(key)) {
+                    Main.LOG().debug("  - {}", f.getName());
+                }
+            }
+            Main.LOG().debug("Settings: ");
+            for(final Map.Entry<String, String> entry : properties.entrySet()) {
+                Main.LOG().debug("- {}={}", entry.getKey(), entry.getValue());
+            }
+            Main.LOG().debug("Configurations: ");
+            for(final Object[] entry : context.getConfigurations()) {
+                if ( entry[1] != null ) {
+                    Main.LOG().debug("- Factory {} - {}", entry[1], entry[0]);
+                } else {
+                    Main.LOG().debug("- {}", entry[0]);
+                }
+            }
+            Main.LOG().debug("");
+        }
+        long time = System.currentTimeMillis();
+
+        final Class<?> runnerClass = cl.loadClass(this.getClass().getPackage().getName() + ".FrameworkRunner");
+        final Constructor<?> constructor = runnerClass.getDeclaredConstructor(Map.class, Map.class, List.class, List.class);
+        constructor.setAccessible(true);
+        constructor.newInstance(properties,
+                context.getBundleMap(),
+                context.getConfigurations(),
+                context.getInstallableArtifacts());
+
+        Main.LOG().debug("Startup took: " + (System.currentTimeMillis() - time));
+        // nothing else to do, constructor starts everything
+    }
+}
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkRunner.java b/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkRunner.java
new file mode 100644
index 0000000..5d95cef
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkRunner.java
@@ -0,0 +1,70 @@
+/*
+ * 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.feature.launcher.impl.launchers;
+
+import org.osgi.framework.BundleException;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.launch.FrameworkFactory;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+/**
+ * Launcher directly using the OSGi launcher API.
+ */
+public class FrameworkRunner extends AbstractRunner {
+
+    public FrameworkRunner(final Map<String, String> frameworkProperties,
+            final Map<Integer, List<File>> bundlesMap,
+            final List<Object[]> configurations,
+            final List<File> installables) throws Exception {
+        super(configurations, installables);
+
+        final ServiceLoader<FrameworkFactory> loader = ServiceLoader.load(FrameworkFactory.class);
+        FrameworkFactory factory = null;
+        for(FrameworkFactory f : loader) {
+            factory = f;
+            break;
+        }
+        if ( factory == null ) {
+            throw new Exception("Unable to locate framework factory.");
+        }
+
+        // create the framework
+        final Framework framework = factory.newFramework(frameworkProperties);
+        // initialize the framework
+        framework.init();
+
+        Runtime.getRuntime().addShutdownHook(new Thread() {
+            @Override
+            public void run() {
+                try {
+                    framework.stop();
+                } catch (final BundleException e) {
+                    // ignore
+                }
+            }
+        });
+
+        this.setupFramework(framework, bundlesMap);
+
+        // finally start
+        framework.start();
+    }
+}
diff --git a/src/main/java/org/apache/sling/feature/launcher/spi/Launcher.java b/src/main/java/org/apache/sling/feature/launcher/spi/Launcher.java
new file mode 100644
index 0000000..a1ced11
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/launcher/spi/Launcher.java
@@ -0,0 +1,26 @@
+/*
+ * 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.feature.launcher.spi;
+
+import org.apache.sling.feature.Application;
+
+public interface Launcher {
+
+    void prepare(LauncherPrepareContext context, Application app) throws Exception;
+
+    void run(LauncherRunContext context, ClassLoader cl) throws Exception;
+}
diff --git a/src/main/java/org/apache/sling/feature/launcher/spi/LauncherPrepareContext.java b/src/main/java/org/apache/sling/feature/launcher/spi/LauncherPrepareContext.java
new file mode 100644
index 0000000..6d6f02b
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/launcher/spi/LauncherPrepareContext.java
@@ -0,0 +1,32 @@
+/*
+ * 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.feature.launcher.spi;
+
+import org.apache.sling.feature.ArtifactId;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * This is the context for the launcher
+ */
+public interface LauncherPrepareContext {
+
+    void addAppJar(File jar);
+
+    File getArtifactFile(ArtifactId artifact) throws IOException;
+}
diff --git a/src/main/java/org/apache/sling/feature/launcher/spi/LauncherRunContext.java b/src/main/java/org/apache/sling/feature/launcher/spi/LauncherRunContext.java
new file mode 100644
index 0000000..20c95a9
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/launcher/spi/LauncherRunContext.java
@@ -0,0 +1,58 @@
+/*
+ * 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.feature.launcher.spi;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This is the context for the launcher
+ */
+public interface LauncherRunContext {
+
+    /**
+     * Map of framework properties to be set when the framework is created.
+     * @return The map with the framework properties.
+     */
+    Map<String, String> getFrameworkProperties();
+
+    /**
+     * Bundle map, key is the start level, value is a list of files.
+     * @return The bundle map, might be empty
+     */
+    Map<Integer, List<File>> getBundleMap();
+
+    /**
+     * List of configurations.
+     * The value in each is an object array with three values
+     * <ol>
+     *  <li>The PID
+     *  <li>The factory PID or {@code null}
+     *  <li>The dictionary with the properties
+     * </ol>
+     * We can't use a custom object due to class loading restrictions.
+     * @return The list, might be empty
+     */
+    List<Object[]> getConfigurations();
+
+    /**
+     * List of installable artifacts.
+     * @return The list of files. The list might be empty.
+     */
+    List<File> getInstallableArtifacts();
+}

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-org-apache-sling-feature-launcher] 11/16: Rename packages

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

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git

commit a739692f53ff5ffcc5c9987232a7b2a7498433e2
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Wed Apr 18 10:26:45 2018 +0200

    Rename packages
---
 .../apache/sling/feature/launcher/impl/FeatureProcessor.java   | 10 +++++-----
 .../org/apache/sling/feature/launcher/impl/LauncherConfig.java |  4 ++--
 src/main/java/org/apache/sling/feature/launcher/impl/Main.java |  4 ++--
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
index 5741952..2f2d7b0 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
@@ -29,14 +29,14 @@ import org.apache.sling.feature.Artifact;
 import org.apache.sling.feature.Configuration;
 import org.apache.sling.feature.Extension;
 import org.apache.sling.feature.ExtensionType;
+import org.apache.sling.feature.io.ArtifactHandler;
+import org.apache.sling.feature.io.ArtifactManager;
+import org.apache.sling.feature.io.json.ApplicationJSONReader;
+import org.apache.sling.feature.io.json.ApplicationJSONWriter;
 import org.apache.sling.feature.launcher.impl.LauncherConfig.StartupMode;
 import org.apache.sling.feature.resolver.FrameworkResolver;
 import org.apache.sling.feature.support.FeatureUtil;
 import org.apache.sling.feature.support.SlingConstants;
-import org.apache.sling.feature.support.artifact.ArtifactHandler;
-import org.apache.sling.feature.support.artifact.ArtifactManager;
-import org.apache.sling.feature.support.json.ApplicationJSONReader;
-import org.apache.sling.feature.support.json.ApplicationJSONWriter;
 import org.apache.sling.feature.support.resolver.FeatureResolver;
 
 public class FeatureProcessor {
@@ -65,7 +65,7 @@ public class FeatureProcessor {
         } else {
             try (FeatureResolver resolver = new FrameworkResolver(artifactManager, Collections.emptyMap())) {
                 app = FeatureUtil.assembleApplication(null, artifactManager, resolver,
-                       org.apache.sling.feature.support.io.FileUtils.getFeatureFiles(config.getHomeDirectory(), config.getFeatureFiles()).toArray(new String[0]));
+                       org.apache.sling.feature.io.FileUtils.getFeatureFiles(config.getHomeDirectory(), config.getFeatureFiles()).toArray(new String[0]));
             } catch (Exception ex) {
                 Main.LOG().error("Error while assembling application: {}", ex.getMessage(), ex);
                 System.exit(1);
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java b/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
index 9737ca9..1feb931 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
@@ -16,8 +16,8 @@
  */
 package org.apache.sling.feature.launcher.impl;
 
-import org.apache.sling.feature.support.artifact.ArtifactManagerConfig;
-import org.apache.sling.feature.support.artifact.spi.ArtifactProviderContext;
+import org.apache.sling.feature.io.ArtifactManagerConfig;
+import org.apache.sling.feature.io.spi.ArtifactProviderContext;
 
 import java.io.File;
 import java.io.IOException;
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/Main.java b/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
index 7a7f48d..6593319 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
@@ -33,11 +33,11 @@ import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
 import org.apache.sling.feature.Application;
 import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.io.ArtifactHandler;
+import org.apache.sling.feature.io.ArtifactManager;
 import org.apache.sling.feature.launcher.impl.launchers.FrameworkLauncher;
 import org.apache.sling.feature.launcher.spi.Launcher;
 import org.apache.sling.feature.launcher.spi.LauncherPrepareContext;
-import org.apache.sling.feature.support.artifact.ArtifactHandler;
-import org.apache.sling.feature.support.artifact.ArtifactManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-org-apache-sling-feature-launcher] 09/16: Split feature util into io and assembly parts

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

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git

commit 3971cf3456fb29f76803a4a605f312a3ce43b790
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Tue Apr 17 16:56:40 2018 +0200

    Split feature util into io and assembly parts
---
 .../java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
index 12c0dbe..6fd5fce 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
@@ -65,7 +65,7 @@ public class FeatureProcessor {
         } else {
             try (FeatureResolver resolver = new FrameworkResolver(artifactManager, Collections.emptyMap())) {
                 app = FeatureUtil.assembleApplication(null, artifactManager, resolver,
-                       FeatureUtil.getFeatureFiles(config.getHomeDirectory(), config.getFeatureFiles()).toArray(new String[0]));
+                       org.apache.sling.feature.support.io.FeatureUtil.getFeatureFiles(config.getHomeDirectory(), config.getFeatureFiles()).toArray(new String[0]));
             } catch (Exception ex) {
                 Main.LOG().error("Error while assembling application: {}", ex.getMessage(), ex);
                 System.exit(1);

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-org-apache-sling-feature-launcher] 05/16: Move the process package from the feature api module to the support one.

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

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git

commit 6d459f0b151a1c8f74e255a74fb618c9ba5ebebc
Author: David Bosschaert <da...@gmail.com>
AuthorDate: Wed Apr 11 16:51:50 2018 +0100

    Move the process package from the feature api module to the support one.
    
    Also move the associated tests.
---
 .../java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
index d4e70e2..8194698 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
@@ -30,13 +30,13 @@ import org.apache.sling.feature.Configuration;
 import org.apache.sling.feature.Extension;
 import org.apache.sling.feature.ExtensionType;
 import org.apache.sling.feature.launcher.impl.LauncherConfig.StartupMode;
-import org.apache.sling.feature.process.FeatureResolver;
 import org.apache.sling.feature.resolver.FrameworkResolver;
 import org.apache.sling.feature.support.ArtifactHandler;
 import org.apache.sling.feature.support.ArtifactManager;
 import org.apache.sling.feature.support.FeatureUtil;
 import org.apache.sling.feature.support.json.ApplicationJSONReader;
 import org.apache.sling.feature.support.json.ApplicationJSONWriter;
+import org.apache.sling.feature.support.process.FeatureResolver;
 
 public class FeatureProcessor {
 

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-org-apache-sling-feature-launcher] 04/16: Update to parent pom 33

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

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git

commit f91d78419f25557d3737322b6a269739a06e36c6
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Mon Feb 26 13:24:32 2018 +0100

    Update to parent pom 33
---
 pom.xml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 8e1d828..0c73499 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,7 +16,7 @@
     <parent>
         <groupId>org.apache.sling</groupId>
         <artifactId>sling</artifactId>
-        <version>32</version>
+        <version>33</version>
         <relativePath />
     </parent>
 
@@ -78,6 +78,8 @@
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>osgi.core</artifactId>
+            <version>6.0.0</version>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-org-apache-sling-feature-launcher] 16/16: Use felix utils ResourceBuilder and Parser instead of the ManifestParser and ManifestUtil. As with that the feature-support module is empty, remove it.

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

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git

commit ec6b9d8eed31e4f1f480da8f1cafb9d48aebe733
Author: Karl Pauls <kp...@adobe.com>
AuthorDate: Thu Apr 26 12:00:25 2018 +0200

    Use felix utils ResourceBuilder and Parser instead of the ManifestParser and ManifestUtil. As with that the feature-support module is empty, remove it.
---
 pom.xml | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/pom.xml b/pom.xml
index a71522d..fdcd201 100644
--- a/pom.xml
+++ b/pom.xml
@@ -55,7 +55,7 @@
                         <outputDirectory>${project.build.directory}/classes</outputDirectory>
                         <overWriteReleases>false</overWriteReleases>
                         <overWriteSnapshots>true</overWriteSnapshots>
-                        <includeArtifactIds>org.apache.sling.feature,org.apache.sling.feature.support,org.apache.sling.commons.johnzon,org.apache.felix.converter,commons-cli,slf4j-api,slf4j-simple,osgi.core</includeArtifactIds>
+                        <includeArtifactIds>org.apache.sling.feature,org.apache.sling.commons.johnzon,org.apache.felix.converter,commons-cli,slf4j-api,slf4j-simple,osgi.core</includeArtifactIds>
                     </configuration>
                 </execution>
             </executions>
@@ -111,11 +111,6 @@
             <version>0.0.1-SNAPSHOT</version>
         </dependency>
         <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.feature.support</artifactId>
-            <version>0.0.1-SNAPSHOT</version>
-        </dependency>
-        <dependency>
             <groupId>org.apache.felix</groupId>
             <artifactId>org.apache.felix.converter</artifactId>
             <version>0.1.0-SNAPSHOT</version>

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-org-apache-sling-feature-launcher] 13/16: [Sling Feature Model] Split off IO packages into separate module.

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

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git

commit 14bc99e18b7b0cb7f20e85c5835b1e4411ec2c78
Author: David Bosschaert <da...@gmail.com>
AuthorDate: Wed Apr 25 10:58:43 2018 +0100

    [Sling Feature Model] Split off IO packages into separate module.
---
 pom.xml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/pom.xml b/pom.xml
index fb1574b..a71522d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -102,6 +102,11 @@
         </dependency>
         <dependency>
             <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.feature.io</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.feature.resolver</artifactId>
             <version>0.0.1-SNAPSHOT</version>
         </dependency>

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-org-apache-sling-feature-launcher] 12/16: Replace SubstVarUtil with Apache Commons Lang StrSubstitutor

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

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git

commit 1ccd93e01864204ea166d3363bd5d3cab1111797
Author: David Bosschaert <da...@gmail.com>
AuthorDate: Tue Apr 24 12:45:41 2018 +0100

    Replace SubstVarUtil with Apache Commons Lang StrSubstitutor
---
 pom.xml                                                |  5 +++++
 .../launcher/impl/launchers/FrameworkLauncher.java     | 18 ++++++++++++++++--
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 0c73499..fb1574b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -76,6 +76,11 @@
 
     <dependencies>
         <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>2.6</version>
+        </dependency>
+        <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>osgi.core</artifactId>
             <version>6.0.0</version>
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java b/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java
index 8bb5fdc..ded2239 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java
@@ -16,12 +16,13 @@
  */
 package org.apache.sling.feature.launcher.impl.launchers;
 
+import org.apache.commons.lang.text.StrLookup;
+import org.apache.commons.lang.text.StrSubstitutor;
 import org.apache.sling.feature.Application;
 import org.apache.sling.feature.launcher.impl.Main;
 import org.apache.sling.feature.launcher.spi.Launcher;
 import org.apache.sling.feature.launcher.spi.LauncherPrepareContext;
 import org.apache.sling.feature.launcher.spi.LauncherRunContext;
-import org.apache.sling.feature.support.util.SubstVarUtil;
 
 import java.io.File;
 import java.lang.reflect.Constructor;
@@ -46,9 +47,22 @@ public class FrameworkLauncher implements Launcher {
      */
     @Override
     public void run(final LauncherRunContext context, final ClassLoader cl) throws Exception {
+        StrSubstitutor ss = new StrSubstitutor(new StrLookup() {
+            @Override
+            public String lookup(String key) {
+                // Normally if a variable cannot be found, StrSubstitutor will
+                // leave the raw variable in place. We need to replace it with
+                // nothing in that case.
+
+                String val = context.getFrameworkProperties().get(key);
+                return val != null ? val : "";
+            }
+        });
+        ss.setEnableSubstitutionInVariables(true);
+
         Map<String, String> properties = new HashMap<>();
         context.getFrameworkProperties().forEach((key, value) -> {
-            properties.put(key, SubstVarUtil.substVars(value, key,null, context.getFrameworkProperties()));
+            properties.put(key, ss.replace(value));
         });
         if ( Main.LOG().isDebugEnabled() ) {
             Main.LOG().debug("Bundles:");

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-org-apache-sling-feature-launcher] 06/16: Move resolving to separate package

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

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git

commit 0c1a241f2e1c277dcd6128e7f2c78139541c23b3
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Tue Apr 17 09:25:12 2018 +0200

    Move resolving to separate package
---
 .../java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
index 8194698..99d3c47 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
@@ -36,7 +36,7 @@ import org.apache.sling.feature.support.ArtifactManager;
 import org.apache.sling.feature.support.FeatureUtil;
 import org.apache.sling.feature.support.json.ApplicationJSONReader;
 import org.apache.sling.feature.support.json.ApplicationJSONWriter;
-import org.apache.sling.feature.support.process.FeatureResolver;
+import org.apache.sling.feature.support.resolver.FeatureResolver;
 
 public class FeatureProcessor {
 

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-org-apache-sling-feature-launcher] 15/16: [Feature Model] Move constants from support module to feature module

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

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git

commit 3699fbb950e9ccfaff376ce5451da689af901be6
Author: David Bosschaert <da...@gmail.com>
AuthorDate: Thu Apr 26 09:50:10 2018 +0100

    [Feature Model] Move constants from support module to feature module
    
    EXTENSION_NAME_REPOINIT and EXTENSION_NAME_CONTENT_PACKAGES were moved
    from SlingConstants in feature-support to FeatureConstants in feature.
---
 .../feature/launcher/impl/FeatureProcessor.java    | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
index 149fa96..557ec90 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
@@ -16,19 +16,12 @@
  */
 package org.apache.sling.feature.launcher.impl;
 
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
 import org.apache.sling.feature.Application;
 import org.apache.sling.feature.Artifact;
 import org.apache.sling.feature.Configuration;
 import org.apache.sling.feature.Extension;
 import org.apache.sling.feature.ExtensionType;
+import org.apache.sling.feature.FeatureConstants;
 import org.apache.sling.feature.io.ArtifactHandler;
 import org.apache.sling.feature.io.ArtifactManager;
 import org.apache.sling.feature.io.json.ApplicationJSONReader;
@@ -37,7 +30,14 @@ import org.apache.sling.feature.launcher.impl.LauncherConfig.StartupMode;
 import org.apache.sling.feature.resolver.ApplicationResolverAssembler;
 import org.apache.sling.feature.resolver.FeatureResolver;
 import org.apache.sling.feature.resolver.FrameworkResolver;
-import org.apache.sling.feature.support.SlingConstants;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
 
 public class FeatureProcessor {
 
@@ -114,9 +114,9 @@ public class FeatureProcessor {
                     config.getInstallation().addInstallableArtifact(handler.getFile());
                 }
             } else {
-                if ( ext.getName().equals(SlingConstants.EXTENSION_NAME_REPOINIT) ) {
+                if ( ext.getName().equals(FeatureConstants.EXTENSION_NAME_REPOINIT) ) {
                     if ( ext.getType() != ExtensionType.TEXT ) {
-                        throw new Exception(SlingConstants.EXTENSION_NAME_REPOINIT + " extension must be of type text and not json");
+                        throw new Exception(FeatureConstants.EXTENSION_NAME_REPOINIT + " extension must be of type text and not json");
                     }
                     final Configuration cfg = new Configuration("org.apache.sling.jcr.repoinit.RepositoryInitializer", "repoinit" + String.valueOf(index));
                     index++;

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-org-apache-sling-feature-launcher] 07/16: Move artifact handling to separate package

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

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git

commit 9e9085a9349a4a7017a462c0f9b8756bcad64619
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Tue Apr 17 09:51:30 2018 +0200

    Move artifact handling to separate package
---
 .../java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java | 4 ++--
 .../java/org/apache/sling/feature/launcher/impl/LauncherConfig.java   | 4 ++--
 src/main/java/org/apache/sling/feature/launcher/impl/Main.java        | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
index 99d3c47..af52852 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
@@ -31,9 +31,9 @@ import org.apache.sling.feature.Extension;
 import org.apache.sling.feature.ExtensionType;
 import org.apache.sling.feature.launcher.impl.LauncherConfig.StartupMode;
 import org.apache.sling.feature.resolver.FrameworkResolver;
-import org.apache.sling.feature.support.ArtifactHandler;
-import org.apache.sling.feature.support.ArtifactManager;
 import org.apache.sling.feature.support.FeatureUtil;
+import org.apache.sling.feature.support.artifact.ArtifactHandler;
+import org.apache.sling.feature.support.artifact.ArtifactManager;
 import org.apache.sling.feature.support.json.ApplicationJSONReader;
 import org.apache.sling.feature.support.json.ApplicationJSONWriter;
 import org.apache.sling.feature.support.resolver.FeatureResolver;
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java b/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
index 56095b9..9737ca9 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
@@ -16,8 +16,8 @@
  */
 package org.apache.sling.feature.launcher.impl;
 
-import org.apache.sling.feature.support.ArtifactManagerConfig;
-import org.apache.sling.feature.support.spi.ArtifactProviderContext;
+import org.apache.sling.feature.support.artifact.ArtifactManagerConfig;
+import org.apache.sling.feature.support.artifact.spi.ArtifactProviderContext;
 
 import java.io.File;
 import java.io.IOException;
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/Main.java b/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
index 31050fe..7a7f48d 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
@@ -36,8 +36,8 @@ import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.launcher.impl.launchers.FrameworkLauncher;
 import org.apache.sling.feature.launcher.spi.Launcher;
 import org.apache.sling.feature.launcher.spi.LauncherPrepareContext;
-import org.apache.sling.feature.support.ArtifactHandler;
-import org.apache.sling.feature.support.ArtifactManager;
+import org.apache.sling.feature.support.artifact.ArtifactHandler;
+import org.apache.sling.feature.support.artifact.ArtifactManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-org-apache-sling-feature-launcher] 02/16: Start changing start level handling to start order handling

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

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git

commit 4487e24a5e8366ab8febfd4282b0d8011e83dc03
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Thu Jan 18 16:14:50 2018 +0100

    Start changing start level handling to start order handling
---
 .../java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
index 14eaf9c..16c244b 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
@@ -85,7 +85,7 @@ public class FeatureProcessor {
     public static void prepareLauncher(final LauncherConfig config,
             final ArtifactManager artifactManager,
             final Application app) throws Exception {
-        for(final Map.Entry<Integer, List<Artifact>> entry : app.getBundles().getBundlesByStartLevel().entrySet()) {
+        for(final Map.Entry<Integer, List<Artifact>> entry : app.getBundles().getBundlesByStartOrder().entrySet()) {
             for(final Artifact a : entry.getValue()) {
                 final ArtifactHandler handler = artifactManager.getArtifactHandler(":" + a.getId().toMvnPath());
                 final File artifactFile = handler.getFile();

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-org-apache-sling-feature-launcher] 08/16: Move Sling specific constants into support module

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

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git

commit d19a9698c4baf0158f2abf83481686df958e8122
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Tue Apr 17 10:31:04 2018 +0200

    Move Sling specific constants into support module
---
 .../org/apache/sling/feature/launcher/impl/FeatureProcessor.java     | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
index af52852..12c0dbe 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
@@ -32,6 +32,7 @@ import org.apache.sling.feature.ExtensionType;
 import org.apache.sling.feature.launcher.impl.LauncherConfig.StartupMode;
 import org.apache.sling.feature.resolver.FrameworkResolver;
 import org.apache.sling.feature.support.FeatureUtil;
+import org.apache.sling.feature.support.SlingConstants;
 import org.apache.sling.feature.support.artifact.ArtifactHandler;
 import org.apache.sling.feature.support.artifact.ArtifactManager;
 import org.apache.sling.feature.support.json.ApplicationJSONReader;
@@ -113,9 +114,9 @@ public class FeatureProcessor {
                     config.getInstallation().addInstallableArtifact(handler.getFile());
                 }
             } else {
-                if ( ext.getName().equals(Extension.NAME_REPOINIT) ) {
+                if ( ext.getName().equals(SlingConstants.EXTENSION_NAME_REPOINIT) ) {
                     if ( ext.getType() != ExtensionType.TEXT ) {
-                        throw new Exception(Extension.NAME_REPOINIT + " extension must be of type text and not json");
+                        throw new Exception(SlingConstants.EXTENSION_NAME_REPOINIT + " extension must be of type text and not json");
                     }
                     final Configuration cfg = new Configuration("org.apache.sling.jcr.repoinit.RepositoryInitializer", "repoinit" + String.valueOf(index));
                     index++;

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-org-apache-sling-feature-launcher] 03/16: SLING-7512 Order features based on their dependencies.

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

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git

commit 373e578e57f6944446f37e043413bb79720d0262
Author: David Bosschaert <bo...@adobe.com>
AuthorDate: Fri Feb 23 13:42:28 2018 +0000

    SLING-7512 Order features based on their dependencies.
    
    Very initial implementation which contains the refactoring of
    Requirements and Capabilities to use the OSGi ones.
---
 pom.xml                                                     |  5 +++++
 .../sling/feature/launcher/impl/FeatureProcessor.java       | 13 +++++++++++--
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 6bf9943..8e1d828 100644
--- a/pom.xml
+++ b/pom.xml
@@ -95,6 +95,11 @@
         </dependency>
         <dependency>
             <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.feature.resolver</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.feature.support</artifactId>
             <version>0.0.1-SNAPSHOT</version>
         </dependency>
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
index 16c244b..d4e70e2 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
@@ -20,6 +20,7 @@ import java.io.File;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -29,6 +30,8 @@ import org.apache.sling.feature.Configuration;
 import org.apache.sling.feature.Extension;
 import org.apache.sling.feature.ExtensionType;
 import org.apache.sling.feature.launcher.impl.LauncherConfig.StartupMode;
+import org.apache.sling.feature.process.FeatureResolver;
+import org.apache.sling.feature.resolver.FrameworkResolver;
 import org.apache.sling.feature.support.ArtifactHandler;
 import org.apache.sling.feature.support.ArtifactManager;
 import org.apache.sling.feature.support.FeatureUtil;
@@ -46,7 +49,7 @@ public class FeatureProcessor {
     public static Application createApplication(final LauncherConfig config,
             final ArtifactManager artifactManager)
     throws IOException {
-        final Application app;
+        Application app = null;
         if ( config.getApplicationFile() != null ) {
             String absoluteArg = config.getApplicationFile();
             if ( absoluteArg.indexOf(":") < 2 ) {
@@ -59,7 +62,13 @@ public class FeatureProcessor {
             }
 
         } else {
-           app = FeatureUtil.assembleApplication(null, artifactManager, FeatureUtil.getFeatureFiles(config.getHomeDirectory(), config.getFeatureFiles()).toArray(new String[0]));
+            try (FeatureResolver resolver = new FrameworkResolver(artifactManager, Collections.emptyMap())) {
+                app = FeatureUtil.assembleApplication(null, artifactManager, resolver,
+                       FeatureUtil.getFeatureFiles(config.getHomeDirectory(), config.getFeatureFiles()).toArray(new String[0]));
+            } catch (Exception ex) {
+                Main.LOG().error("Error while assembling application: {}", ex.getMessage(), ex);
+                System.exit(1);
+            }
         }
 
         // write application back

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-org-apache-sling-feature-launcher] 14/16: [Sling Feature Model] Refactor FeatureUtil out of the support module

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

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git

commit e5c47f92389dc6ef11969a30af003fdd83f093c1
Author: David Bosschaert <da...@gmail.com>
AuthorDate: Wed Apr 25 13:40:18 2018 +0100

    [Sling Feature Model] Refactor FeatureUtil out of the support module
    
    Also move the Resolver API to the resolver module.
---
 .../org/apache/sling/feature/launcher/impl/FeatureProcessor.java  | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
index 2f2d7b0..149fa96 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
@@ -34,10 +34,10 @@ import org.apache.sling.feature.io.ArtifactManager;
 import org.apache.sling.feature.io.json.ApplicationJSONReader;
 import org.apache.sling.feature.io.json.ApplicationJSONWriter;
 import org.apache.sling.feature.launcher.impl.LauncherConfig.StartupMode;
+import org.apache.sling.feature.resolver.ApplicationResolverAssembler;
+import org.apache.sling.feature.resolver.FeatureResolver;
 import org.apache.sling.feature.resolver.FrameworkResolver;
-import org.apache.sling.feature.support.FeatureUtil;
 import org.apache.sling.feature.support.SlingConstants;
-import org.apache.sling.feature.support.resolver.FeatureResolver;
 
 public class FeatureProcessor {
 
@@ -64,8 +64,8 @@ public class FeatureProcessor {
 
         } else {
             try (FeatureResolver resolver = new FrameworkResolver(artifactManager, Collections.emptyMap())) {
-                app = FeatureUtil.assembleApplication(null, artifactManager, resolver,
-                       org.apache.sling.feature.io.FileUtils.getFeatureFiles(config.getHomeDirectory(), config.getFeatureFiles()).toArray(new String[0]));
+                app = ApplicationResolverAssembler.assembleApplication(null, artifactManager, resolver,
+                       org.apache.sling.feature.io.IOUtils.getFeatureFiles(config.getHomeDirectory(), config.getFeatureFiles()).toArray(new String[0]));
             } catch (Exception ex) {
                 Main.LOG().error("Error while assembling application: {}", ex.getMessage(), ex);
                 System.exit(1);

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.

[sling-org-apache-sling-feature-launcher] 10/16: Rename to FileUtils and use constants

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

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git

commit 13bf1e67adfb3bdcffde61def19dac7693ad20de
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Wed Apr 18 09:55:21 2018 +0200

    Rename to FileUtils and use constants
---
 .../java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
index 6fd5fce..5741952 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
@@ -65,7 +65,7 @@ public class FeatureProcessor {
         } else {
             try (FeatureResolver resolver = new FrameworkResolver(artifactManager, Collections.emptyMap())) {
                 app = FeatureUtil.assembleApplication(null, artifactManager, resolver,
-                       org.apache.sling.feature.support.io.FeatureUtil.getFeatureFiles(config.getHomeDirectory(), config.getFeatureFiles()).toArray(new String[0]));
+                       org.apache.sling.feature.support.io.FileUtils.getFeatureFiles(config.getHomeDirectory(), config.getFeatureFiles()).toArray(new String[0]));
             } catch (Exception ex) {
                 Main.LOG().error("Error while assembling application: {}", ex.getMessage(), ex);
                 System.exit(1);

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.