This is an automated email from the ASF dual-hosted git repository.
pauls pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git
The following commit(s) were added to refs/heads/master by this push:
new cbad8993 Add a first version of an atomos launcher
cbad8993 is described below
commit cbad8993f277a4fe6a22a07bc62ed8c5a0fb3508
Author: Karl Pauls <[email protected]>
AuthorDate: Wed Oct 4 13:36:34 2023 +0200
Add a first version of an atomos launcher
---
atomosfeaturelauncher/.gitignore | 2 +
atomosfeaturelauncher/pom.xml | 130 ++++++++++
.../src/main/features/feature.json | 265 +++++++++++++++++++++
atomosfeaturelauncher/src/main/features/up.json | 5 +
.../launcher/atomos/AtomosArtifactProvider.java | 60 +++++
.../launcher/atomos/AtomosFrameworkFactory.java | 45 ++++
.../feature/launcher/atomos/AtomosLaucherMain.java | 48 ++++
.../feature/launcher/atomos/AtomosLauncher.java | 88 +++++++
.../feature/launcher/atomos/AtomosRunner.java | 150 ++++++++++++
...sling.feature.io.artifacts.spi.ArtifactProvider | 1 +
.../org.apache.sling.feature.launcher.spi.Launcher | 1 +
11 files changed, 795 insertions(+)
diff --git a/atomosfeaturelauncher/.gitignore b/atomosfeaturelauncher/.gitignore
new file mode 100644
index 00000000..c9e18c8e
--- /dev/null
+++ b/atomosfeaturelauncher/.gitignore
@@ -0,0 +1,2 @@
+target
+launcher
diff --git a/atomosfeaturelauncher/pom.xml b/atomosfeaturelauncher/pom.xml
new file mode 100644
index 00000000..48bbdbfb
--- /dev/null
+++ b/atomosfeaturelauncher/pom.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<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/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>sling-bundle-parent</artifactId>
+ <version>35</version>
+ <relativePath/>
+ </parent>
+
+ <artifactId>org.apache.sling.feature.launcher.atomos</artifactId>
+ <name>Apache Sling Atomos feature launcher</name>
+ <description></description>
+ <version>0.0.1-SNAPSHOT</version>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>slingfeature-maven-plugin</artifactId>
+ <version>1.1.6</version>
+ <extensions>true</extensions>
+ <executions>
+ <execution>
+ <id>attach</id>
+ <goals>
+ <goal>attach-features</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>embed</id>
+ <goals>
+ <goal>embed-features</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>create-repository</id>
+ <goals>
+ <goal>repository</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>2.2.5.RELEASE</version>
+ <configuration>
+
<mainClass>org.apache.sling.feature.launcher.atomos.AtomosLaucherMain</mainClass>
+ <classifier>fatjar</classifier>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>biz.aQute.bnd</groupId>
+ <artifactId>bnd-baseline-maven-plugin</artifactId>
+ <configuration>
+ <failOnMissing>false</failOnMissing>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.rat</groupId>
+ <artifactId>apache-rat-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>readme.md</exclude>
+
<exclude>src/main/resources/META-INF/services/**</exclude>
+ <exclude>**/*.properties</exclude>
+ <exclude>launcher/**</exclude>
+ <exclude>**/*.patch</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>osgi.core</artifactId>
+ <version>8.0.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.framework</artifactId>
+ <version>7.0.5</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.feature.launcher</artifactId>
+ <version>1.2.4</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.atomos</artifactId>
+ <version>1.0.1-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/atomosfeaturelauncher/src/main/features/feature.json
b/atomosfeaturelauncher/src/main/features/feature.json
new file mode 100644
index 00000000..411e2378
--- /dev/null
+++ b/atomosfeaturelauncher/src/main/features/feature.json
@@ -0,0 +1,265 @@
+{
+ "bundles":[
+{
+ "id":"commons-fileupload:commons-fileupload:1.5",
+ "start-order":"1"
+ },
+ {
+ "id":"commons-io:commons-io:2.11.0",
+ "start-order":"1"
+ },
+ {
+ "id":"org.osgi:org.osgi.util.function:1.2.0",
+ "start-order":"1"
+ },
+ {
+ "id":"org.osgi:org.osgi.util.promise:1.2.0",
+ "start-order":"1"
+ },
+ {
+ "id":"org.osgi:org.osgi.service.component:1.5.0",
+ "start-order":"1"
+ },
+ {
+ "id":"org.osgi:org.osgi.util.converter:1.0.9",
+ "start-order":"1"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.commons.log:5.4.2",
+ "start-order":"1"
+ },
+ {
+ "id":"org.apache.commons:commons-lang3:3.12.0",
+ "start-order":"1"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.commons.logservice:1.1.0",
+ "start-order":"1"
+ },
+ {
+ "id":"org.apache.felix:org.apache.felix.log:1.2.6",
+ "start-order":"1"
+ },
+ {
+ "id":"org.slf4j:jcl-over-slf4j:1.7.36",
+ "start-order":"1"
+ },
+ {
+ "id":"org.slf4j:log4j-over-slf4j:1.7.36",
+ "start-order":"1"
+ },
+ {
+ "id":"org.slf4j:slf4j-api:1.7.36",
+ "start-order":"1"
+ },
+ {
+ "id":"org.apache.logging.log4j:log4j-api:2.20.0",
+ "start-order":1
+ },
+ {
+ "id":"org.apache.logging.log4j:log4j-to-slf4j:2.20.0",
+ "start-order":1
+ },
+ {
+ "id":"org.apache.felix:org.apache.felix.configadmin:1.9.26",
+ "start-order":"1"
+ },
+ {
+ "id":"org.apache.felix:org.apache.felix.eventadmin:1.6.4",
+ "start-order":"2"
+ },
+ {
+ "id":"org.apache.felix:org.apache.felix.metatype:1.2.4",
+ "start-order":"2"
+ },
+ {
+ "id":"org.apache.felix:org.apache.felix.inventory:1.1.0",
+ "start-order":"2"
+ },
+ {
+ "id":"org.apache.felix:org.apache.felix.http.servlet-api:2.0.0",
+ "start-order":"1"
+ },
+ {
+ "id":"org.apache.felix:org.apache.felix.http.jetty:4.2.8",
+ "start-order":"2"
+ },
+ {
+ "id":"org.apache.felix:org.apache.felix.scr:2.2.6",
+ "start-order":"1"
+ },
+ {
+ "id":"io.dropwizard.metrics:metrics-core:3.2.3",
+ "start-order":"1"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.commons.metrics:1.2.12",
+ "start-order":"1"
+ },
+ {
+ "id":"org.apache.httpcomponents:httpcore-osgi:4.4.15",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.httpcomponents:httpclient-osgi:4.5.13",
+ "start-order":"20"
+ },
+ {
+ "id":"commons-codec:commons-codec:1.15",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.commons:commons-collections4:4.4",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.commons:commons-text:1.10.0",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.api:2.27.0",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.auth.core:1.6.0",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.commons.classloader:1.4.4",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.commons.compiler:2.4.0",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.commons.johnzon:1.2.14",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.commons.mime:2.2.2",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.commons.osgi:2.4.2",
+ "start-order":"20"
+ },
+ {
+
"id":"org.apache.sling:org.apache.sling.sfsresourceprovider:0.0.1-SNAPSHOT",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.serviceusermapper:1.5.6",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.servlets.post:2.5.0",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.settings:1.4.2",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.xss:2.2.0",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.scripting.api:2.2.0",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.scripting.core:2.4.8",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.scripting.spi:1.0.4",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.commons.threads:3.2.22",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.engine:2.14.0",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.resourceresolver:1.10.0",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.servlets.get:2.1.44",
+ "start-order":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.servlets.resolver:2.9.10",
+ "start-order":"20"
+ },
+ {
+
"id":"org.apache.felix:org.apache.felix.webconsole.plugins.packageadmin:1.0.4",
+ "start-order":"10"
+ },
+ {
+ "id":"org.apache.felix:org.apache.felix.webconsole.plugins.ds:2.2.0",
+ "start-order":"10"
+ },
+ {
+ "id":"org.apache.felix:org.apache.felix.webconsole:4.8.8",
+ "start-order":"10"
+ },
+ {
+ "id":"org.apache.felix:org.apache.felix.webconsole.plugins.event:1.1.8",
+ "start-order":"10"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.commons.log.webconsole:1.0.0",
+ "start-order":"10"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.scripting.sightly:1.4.20-1.4.0",
+ "start-order":"10"
+ },
+ {
+
"id":"org.apache.sling:org.apache.sling.scripting.sightly.runtime:1.2.6-1.4.0",
+ "start-order":"10"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.i18n:2.5.18",
+ "start-order":"10"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.commons.scheduler:2.7.12",
+ "start-order":"10"
+ },
+ {
+ "id":"org.apache.tika:tika-core:1.20",
+ "start-order":"10"
+ },
+ {
+ "id":"org.apache.tika:tika-parsers:1.20",
+ "start-order":"10"
+ },
+ {
+ "id": "org.apache.sling:org.apache.sling.models.api:1.5.0"
+ },
+ {
+ "id": "org.apache.geronimo.specs:geronimo-atinject_1.0_spec:1.2"
+ }
+ ],
+ "configurations":{
+ "org.apache.sling.jcr.resource.internal.JcrResourceResolverFactoryImpl":{
+ "resource.resolver.required.providernames":""
+ },
+ "org.apache.sling.sfsresource.impl.SFSResourceProvider~pictures":{
+ "provider.root":"/content",
+ "provider.file":"content"
+ },
+ "org.apache.sling.servlets.resolver.SlingServletResolver":{
+ "servletresolver.mountPathProviders":true
+ }
+ },
+ "framework-properties": {
+ "felix.cm.pm": "featurelauncher"
+ }
+}
diff --git a/atomosfeaturelauncher/src/main/features/up.json
b/atomosfeaturelauncher/src/main/features/up.json
new file mode 100644
index 00000000..b0eac8f0
--- /dev/null
+++ b/atomosfeaturelauncher/src/main/features/up.json
@@ -0,0 +1,5 @@
+{
+ "framework-properties": {
+ "felix.cm.pm": "up"
+ }
+}
\ No newline at end of file
diff --git
a/atomosfeaturelauncher/src/main/java/org/apache/sling/feature/launcher/atomos/AtomosArtifactProvider.java
b/atomosfeaturelauncher/src/main/java/org/apache/sling/feature/launcher/atomos/AtomosArtifactProvider.java
new file mode 100644
index 00000000..0ed1145b
--- /dev/null
+++
b/atomosfeaturelauncher/src/main/java/org/apache/sling/feature/launcher/atomos/AtomosArtifactProvider.java
@@ -0,0 +1,60 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.atomos;
+
+import org.apache.sling.feature.io.artifacts.spi.ArtifactProvider;
+import org.apache.sling.feature.io.artifacts.spi.ArtifactProviderContext;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+public class AtomosArtifactProvider implements ArtifactProvider {
+ @Override
+ public String getProtocol() {
+ return "*";
+ }
+
+ @Override
+ public void init(ArtifactProviderContext context) throws IOException {
+
+ }
+
+ @Override
+ public void shutdown() {
+
+ }
+
+ @Override
+ public URL getArtifact(String url, String relativeCachePath) {
+ try {
+ final URLStreamHandler dummy = new URLStreamHandler() {
+ @Override
+ protected URLConnection openConnection(URL u) throws
IOException {
+ return new URL(url).openConnection();
+ }
+ };
+ return new URL(new URL(null, "missing:", dummy),
relativeCachePath, dummy);
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git
a/atomosfeaturelauncher/src/main/java/org/apache/sling/feature/launcher/atomos/AtomosFrameworkFactory.java
b/atomosfeaturelauncher/src/main/java/org/apache/sling/feature/launcher/atomos/AtomosFrameworkFactory.java
new file mode 100644
index 00000000..96f4a386
--- /dev/null
+++
b/atomosfeaturelauncher/src/main/java/org/apache/sling/feature/launcher/atomos/AtomosFrameworkFactory.java
@@ -0,0 +1,45 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+package org.apache.sling.feature.launcher.atomos;
+
+import org.apache.felix.atomos.Atomos;
+import org.osgi.framework.connect.ConnectFrameworkFactory;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.launch.FrameworkFactory;
+
+import java.util.Map;
+import java.util.ServiceLoader;
+
+public class AtomosFrameworkFactory implements FrameworkFactory {
+ private final Atomos m_atomos;
+
+ public AtomosFrameworkFactory(Atomos atomos) {
+ m_atomos = atomos;
+ }
+
+ @Override
+ public Framework newFramework(Map<String, String> map) {
+ ServiceLoader<ConnectFrameworkFactory> loader =
ServiceLoader.load(ConnectFrameworkFactory.class);
+ ConnectFrameworkFactory factory = loader.iterator().next();
+ map.put("atomos.content.install", "false");
+ Framework framework = factory.newFramework(map,
+ m_atomos.getModuleConnector());
+ return framework;
+ }
+}
diff --git
a/atomosfeaturelauncher/src/main/java/org/apache/sling/feature/launcher/atomos/AtomosLaucherMain.java
b/atomosfeaturelauncher/src/main/java/org/apache/sling/feature/launcher/atomos/AtomosLaucherMain.java
new file mode 100644
index 00000000..956f84fe
--- /dev/null
+++
b/atomosfeaturelauncher/src/main/java/org/apache/sling/feature/launcher/atomos/AtomosLaucherMain.java
@@ -0,0 +1,48 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.atomos;
+
+
+import org.apache.sling.feature.launcher.impl.Main;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class AtomosLaucherMain {
+ public static void main(String[] args) {
+ List<String> launcherArgs = new ArrayList<>(Arrays.asList(args));
+
+ if (args.length > 0) {
+ URL feature =
AtomosLaucherMain.class.getResource("/META-INF/features/feature-" + args[0] +
".json");
+ if (feature != null) {
+ launcherArgs.remove(0);
+ launcherArgs.add(0, feature.toString());
+ launcherArgs.add(0, "-f");
+ }
+ } else {
+ URL feature =
AtomosLaucherMain.class.getResource("/META-INF/features/feature.json");
+ if (feature != null) {
+ launcherArgs.addAll(Arrays.asList("-f", feature.toString()));
+ }
+ }
+ Main.main(launcherArgs.toArray(new String[0]));
+ }
+}
diff --git
a/atomosfeaturelauncher/src/main/java/org/apache/sling/feature/launcher/atomos/AtomosLauncher.java
b/atomosfeaturelauncher/src/main/java/org/apache/sling/feature/launcher/atomos/AtomosLauncher.java
new file mode 100644
index 00000000..4ee7097e
--- /dev/null
+++
b/atomosfeaturelauncher/src/main/java/org/apache/sling/feature/launcher/atomos/AtomosLauncher.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.atomos;
+
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.launcher.impl.launchers.FrameworkLauncher;
+import org.apache.sling.feature.launcher.spi.LauncherPrepareContext;
+import org.slf4j.Logger;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
+
+public class AtomosLauncher extends FrameworkLauncher {
+ @Override
+ public void prepare(LauncherPrepareContext launcherPrepareContext,
ArtifactId artifactId, Feature feature) throws Exception {
+ super.prepare(new LauncherPrepareContext() {
+ @Override
+ public Logger getLogger() {
+ return launcherPrepareContext.getLogger();
+ }
+
+ @Override
+ public void addAppJar(URL url) {
+
+ }
+
+ @Override
+ public URL getArtifactFile(ArtifactId artifactId) throws
IOException {
+ return null;
+ }
+ }, artifactId, feature);
+ }
+
+ @Override
+ protected String getFrameworkRunnerClass() {
+ return AtomosRunner.class.getName();
+ }
+
+ @Override
+ public LauncherClassLoader createClassLoader() {
+ return new AtomosLauncherClassLoader();
+ }
+
+ private static final class AtomosLauncherClassLoader extends
LauncherClassLoader {
+ static {
+ ClassLoader.registerAsParallelCapable();
+ }
+
+ private final ClassLoader parent;
+
+ private AtomosLauncherClassLoader() {
+ parent = getClass().getClassLoader();
+ }
+
+ @Override
+ protected Class<?> findClass(String name) throws
ClassNotFoundException {
+ return parent.loadClass(name);
+ }
+
+ @Override
+ public URL findResource(String name) {
+ return parent.getResource(name);
+ }
+
+ @Override
+ public Enumeration<URL> findResources(String name) throws IOException {
+ return parent.getResources(name);
+ }
+ }
+}
diff --git
a/atomosfeaturelauncher/src/main/java/org/apache/sling/feature/launcher/atomos/AtomosRunner.java
b/atomosfeaturelauncher/src/main/java/org/apache/sling/feature/launcher/atomos/AtomosRunner.java
new file mode 100644
index 00000000..3a3f9386
--- /dev/null
+++
b/atomosfeaturelauncher/src/main/java/org/apache/sling/feature/launcher/atomos/AtomosRunner.java
@@ -0,0 +1,150 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.atomos;
+
+import org.apache.felix.atomos.Atomos;
+import org.apache.felix.atomos.AtomosContent;
+import org.apache.sling.feature.launcher.impl.launchers.FrameworkRunner;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.launch.FrameworkFactory;
+import org.osgi.framework.startlevel.BundleStartLevel;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiConsumer;
+
+public class AtomosRunner extends FrameworkRunner {
+ private final Atomos m_atomos = Atomos.newAtomos();
+ private BiConsumer<URL, Map<String, String>> bundleReporter;
+
+ public AtomosRunner(Map<String, String> frameworkProperties, Map<Integer,
List<URL>> bundlesMap, List<Object[]> configurations, List<URL> installables)
throws Exception {
+ super(frameworkProperties, bundlesMap, configurations, installables);
+ }
+
+ 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);
+ }
+ }
+
+ @Override
+ protected FrameworkFactory getFrameworkFactory() throws Exception {
+ return new AtomosFrameworkFactory(m_atomos);
+ }
+
+ @Override
+ protected void setupFramework(Framework framework, Map<Integer, List<URL>>
bundlesMap) throws BundleException {
+ super.setupFramework(framework, Collections.emptyMap());
+ this.install(framework, bundlesMap);
+ }
+
+ @Override
+ public void setBundleReporter(final BiConsumer<URL, Map<String, String>>
reporter) {
+ this.bundleReporter = reporter;
+ super.setBundleReporter(reporter);
+ }
+
+ 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);
+ }
+
+ private void install(final Framework framework, final Map<Integer,
List<URL>> bundleMap) throws BundleException {
+ final BundleContext bc = framework.getBundleContext();
+ int defaultStartLevel = getProperty(bc, "felix.startlevel.bundle", 1);
+ for (final Integer startLevel : sortStartLevels(bundleMap.keySet(),
defaultStartLevel)) {
+ logger.debug("Installing bundles with start level {}", startLevel);
+
+ for (final URL file : bundleMap.get(startLevel)) {
+ logger.debug("- {}", file);
+
+ final URLStreamHandler dummyHandler = new URLStreamHandler() {
+ @Override
+ protected URLConnection openConnection(URL u) throws
IOException {
+ return null;
+ }
+ };
+ AtomosContent content = m_atomos
+ .getBootLayer()
+ .getAtomosContents().stream()
+ .filter(atomosContent -> {
+ try {
+ return new URL(new URL(null, "missing:",
dummyHandler), atomosContent.getAtomosLocation(),
dummyHandler).getPath().endsWith(file.getPath().substring(file.getPath().lastIndexOf('/')));
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+ })
+ .findFirst().orElseThrow(() -> new
IllegalStateException("Unable to find " + file.getPath() + " on the
classpath!"));
+
+ final Bundle bundle = content.install();
+
+ // fragment?
+ if (!isSystemBundleFragment(bundle) &&
getFragmentHostHeader(bundle) == null) {
+ if (startLevel > 0) {
+
bundle.adapt(BundleStartLevel.class).setStartLevel(startLevel);
+ }
+ bundle.start();
+ }
+
+ if (this.bundleReporter != null) {
+ final Map<String, String> params = new HashMap<>();
+ params.put(Constants.BUNDLE_SYMBOLICNAME,
bundle.getSymbolicName());
+ params.put(Constants.BUNDLE_VERSION,
bundle.getVersion().toString());
+ params.put("Bundle-Id",
String.valueOf(bundle.getBundleId()));
+
+ this.bundleReporter.accept(file, params);
+ }
+ }
+ }
+ }
+}
diff --git
a/atomosfeaturelauncher/src/main/resources/META-INF/services/org.apache.sling.feature.io.artifacts.spi.ArtifactProvider
b/atomosfeaturelauncher/src/main/resources/META-INF/services/org.apache.sling.feature.io.artifacts.spi.ArtifactProvider
new file mode 100644
index 00000000..4e897b11
--- /dev/null
+++
b/atomosfeaturelauncher/src/main/resources/META-INF/services/org.apache.sling.feature.io.artifacts.spi.ArtifactProvider
@@ -0,0 +1 @@
+org.apache.sling.feature.launcher.atomos.AtomosArtifactProvider
\ No newline at end of file
diff --git
a/atomosfeaturelauncher/src/main/resources/META-INF/services/org.apache.sling.feature.launcher.spi.Launcher
b/atomosfeaturelauncher/src/main/resources/META-INF/services/org.apache.sling.feature.launcher.spi.Launcher
new file mode 100644
index 00000000..6c66d9df
--- /dev/null
+++
b/atomosfeaturelauncher/src/main/resources/META-INF/services/org.apache.sling.feature.launcher.spi.Launcher
@@ -0,0 +1 @@
+org.apache.sling.feature.launcher.atomos.AtomosLauncher
\ No newline at end of file