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-whiteboard.git


The following commit(s) were added to refs/heads/master by this push:
     new 844e5939 Native compile changes for atomos feature launcher, config 
and weaver (#114)
844e5939 is described below

commit 844e593916e0b0cfe5ad61a4bd9dccdfd34a1c69
Author: David Bosschaert <bossc...@adobe.com>
AuthorDate: Mon Dec 11 09:40:29 2023 +0000

    Native compile changes for atomos feature launcher, config and weaver (#114)
---
 atomosfeaturelauncher/Dockerfile                   |  15 +-
 atomosfeaturelauncher/build.sh                     |  11 +-
 .../{build.sh => build_nodocker.sh}                |  16 +-
 atomosfeaturelauncher/launch.sh                    |  13 +
 .../src/main/features/feature.json                 |   6 +
 .../feature/launcher/atomos/AtomosLauncher.java    |  28 +-
 .../feature/launcher/atomos/AtomosRunner.java      |  85 +++---
 atomosfeaturelauncherconfig/pom.xml                |   5 +
 .../atomos/config/AtomosConfigLauncher.java        | 320 +++++++++++++++++----
 .../launcher/atomos/config/IndexPlugin.java        |  29 +-
 .../atomos/weaver/impl/AtomosWeaverVisitor.java    |  25 +-
 11 files changed, 404 insertions(+), 149 deletions(-)

diff --git a/atomosfeaturelauncher/Dockerfile b/atomosfeaturelauncher/Dockerfile
index 445e3bbb..f26d5272 100644
--- a/atomosfeaturelauncher/Dockerfile
+++ b/atomosfeaturelauncher/Dockerfile
@@ -2,13 +2,14 @@ FROM ghcr.io/graalvm/native-image:ol8-java17-22.3.3 as native
 
 COPY target/artifacts artifacts
 COPY --chmod=777 build.sh build.sh
-COPY target/atomos-config/atomos_init.sh atomos_init.sh
-COPY target/atomos-config/resource-config.json resource-config.json
-COPY target/atomos-config/reflect-config.json reflect-config.json
-COPY target/atomos-config/proxy-config.json proxy-config.json
-COPY target/atomos-config/jni-config.json jni-config.json
-COPY target/atomos-config/serialization-config.json serialization-config.json
-COPY target/atomos-config/atomos.substrate.jar atomos.substrate.jar
+#COPY target/atomos-config/atomos_init.sh atomos_init.sh
+#COPY target/atomos-config/resource-config.json resource-config.json
+#COPY target/atomos-config/reflect-config.json reflect-config.json
+#COPY target/atomos-config/proxy-config.json proxy-config.json
+#COPY target/atomos-config/jni-config.json jni-config.json
+#COPY target/atomos-config/serialization-config.json serialization-config.json
+#COPY target/atomos-config/atomos.substrate.jar atomos.substrate.jar
+COPY target/atomos-config/app.substrate.jar app.substrate.jar
 
 RUN ./build.sh "-H:+StaticExecutableWithDynamicLibC" "-o launcher" "-Ob"
 
diff --git a/atomosfeaturelauncher/build.sh b/atomosfeaturelauncher/build.sh
old mode 100644
new mode 100755
index 8d1cc8fd..d068e9dc
--- a/atomosfeaturelauncher/build.sh
+++ b/atomosfeaturelauncher/build.sh
@@ -1,7 +1,5 @@
 #!/bin/sh
 
-source ./atomos_init.sh
-
 native-image --verbose \
 -cp 
"artifacts/org/apache/sling/org.apache.sling.feature.launcher.atomos/0.0.1-SNAPSHOT/org.apache.sling.feature.launcher.atomos-0.0.1-SNAPSHOT.jar:\
 
artifacts/org/apache/sling/org.apache.sling.feature.launcher/1.2.4/org.apache.sling.feature.launcher-1.2.4.jar:\
@@ -10,14 +8,9 @@ 
artifacts/org/slf4j/slf4j-simple/1.7.25/slf4j-simple-1.7.25.jar:\
 
artifacts/org/apache/sling/org.apache.sling.feature/1.3.0/org.apache.sling.feature-1.3.0.jar:\
 
artifacts/org/apache/felix/org.apache.felix.cm.json/1.0.6/org.apache.felix.cm.json-1.0.6.jar:\
 artifacts/commons-cli/commons-cli/1.4/commons-cli-1.4.jar:\
-$ATOMOS_CLASSPATH" \
+artifacts/org/apache/felix/org.apache.felix.framework/7.0.5/org.apache.felix.framework-7.0.5.jar:\
+app.substrate.jar" \
 org.apache.sling.feature.launcher.atomos.AtomosLaucherMain \
 --no-fallback --enable-https --enable-http \
-"$ATOMOS_INIT" \
-"-H:ResourceConfigurationFiles=resource-config.json" \
-"-H:ReflectionConfigurationFiles=reflect-config.json" \
-"-H:DynamicProxyConfigurationFiles=proxy-config.json" \
-"-H:JNIConfigurationFiles=jni-config.json" \
-"-H:SerializationConfigurationFiles=serialization-config.json" \
 "$@"
 
diff --git a/atomosfeaturelauncher/build.sh 
b/atomosfeaturelauncher/build_nodocker.sh
old mode 100644
new mode 100755
similarity index 67%
copy from atomosfeaturelauncher/build.sh
copy to atomosfeaturelauncher/build_nodocker.sh
index 8d1cc8fd..b3fabc82
--- a/atomosfeaturelauncher/build.sh
+++ b/atomosfeaturelauncher/build_nodocker.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
-source ./atomos_init.sh
+pushd target
+
+source ./atomos-config/atomos_init.sh
 
 native-image --verbose \
 -cp 
"artifacts/org/apache/sling/org.apache.sling.feature.launcher.atomos/0.0.1-SNAPSHOT/org.apache.sling.feature.launcher.atomos-0.0.1-SNAPSHOT.jar:\
@@ -14,10 +16,12 @@ $ATOMOS_CLASSPATH" \
 org.apache.sling.feature.launcher.atomos.AtomosLaucherMain \
 --no-fallback --enable-https --enable-http \
 "$ATOMOS_INIT" \
-"-H:ResourceConfigurationFiles=resource-config.json" \
-"-H:ReflectionConfigurationFiles=reflect-config.json" \
-"-H:DynamicProxyConfigurationFiles=proxy-config.json" \
-"-H:JNIConfigurationFiles=jni-config.json" \
-"-H:SerializationConfigurationFiles=serialization-config.json" \
+"-H:ResourceConfigurationFiles=atomos-config/resource-config.json" \
+"-H:ReflectionConfigurationFiles=atomos-config/reflect-config.json" \
+"-H:DynamicProxyConfigurationFiles=atomos-config/proxy-config.json" \
+"-H:JNIConfigurationFiles=atomos-config/jni-config.json" \
+"-H:SerializationConfigurationFiles=atomos-config/serialization-config.json" \
+"-o aem_native" "-Ob" \
 "$@"
 
+popd
diff --git a/atomosfeaturelauncher/launch.sh b/atomosfeaturelauncher/launch.sh
new file mode 100755
index 00000000..f7c72861
--- /dev/null
+++ b/atomosfeaturelauncher/launch.sh
@@ -0,0 +1,13 @@
+pushd target
+rm -rf launcher
+java -agentlib:jdwp=transport=dt_socket,address=*:7777,server=y,suspend=n -cp 
"artifacts/org/apache/sling/org.apache.sling.feature.launcher.atomos/0.0.1-SNAPSHOT/org.apache.sling.feature.launcher.atomos-0.0.1-SNAPSHOT.jar:\
+artifacts/org/apache/sling/org.apache.sling.feature.launcher/1.2.4/org.apache.sling.feature.launcher-1.2.4.jar:\
+artifacts/org/apache/felix/org.apache.felix.atomos/1.0.1-SNAPSHOT/org.apache.felix.atomos-1.0.1-SNAPSHOT.jar:\
+artifacts/org/slf4j/slf4j-simple/1.7.25/slf4j-simple-1.7.25.jar:\
+artifacts/org/apache/sling/org.apache.sling.feature/1.3.0/org.apache.sling.feature-1.3.0.jar:\
+artifacts/org/apache/felix/org.apache.felix.cm.json/1.0.6/org.apache.felix.cm.json-1.0.6.jar:\
+artifacts/commons-cli/commons-cli/1.4/commons-cli-1.4.jar:\
+artifacts/org/apache/felix/org.apache.felix.framework/7.0.5/org.apache.felix.framework-7.0.5.jar:\
+atomos-config/app.substrate.jar" \
+org.apache.sling.feature.launcher.atomos.AtomosLaucherMain 
+popd
diff --git a/atomosfeaturelauncher/src/main/features/feature.json 
b/atomosfeaturelauncher/src/main/features/feature.json
index d650cbf8..59b79c97 100644
--- a/atomosfeaturelauncher/src/main/features/feature.json
+++ b/atomosfeaturelauncher/src/main/features/feature.json
@@ -565,6 +565,12 @@
       {
         "name":"org.owasp.esapi.reference.JavaLogFactory",
         "methods":[{"name":"getInstance","parameterTypes":[] }]
+      },
+      {
+        "name":"org.apache.felix.webconsole.SimpleWebConsolePlugin",
+        "queryAllDeclaredMethods":true,
+        "queryAllPublicMethods":true,
+        "methods":[{"name":"getResource","parameterTypes":["java.lang.String"] 
}]
       }
     ],
     "resource-config": {
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
index 4e6972ef..a5e6d7b1 100644
--- 
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
@@ -18,35 +18,15 @@
  
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 package org.apache.sling.feature.launcher.atomos;
 
-import org.apache.felix.atomos.Atomos;
-import org.apache.felix.atomos.AtomosContent;
-import org.apache.felix.atomos.AtomosLayer;
+import java.io.IOException;
+import java.net.URL;
+
 import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.Feature;
-import org.apache.sling.feature.launcher.atomos.weaver.AtomosWeaver;
 import org.apache.sling.feature.launcher.impl.launchers.FrameworkLauncher;
 import org.apache.sling.feature.launcher.spi.LauncherPrepareContext;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Version;
-import org.osgi.framework.connect.ConnectContent;
 import org.slf4j.Logger;
 
-import java.io.File;
-import java.io.IOException;
-import java.net.JarURLConnection;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.security.CodeSource;
-import java.security.ProtectionDomain;
-import java.security.cert.Certificate;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.Optional;
-import java.util.ServiceLoader;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.jar.JarFile;
-
 public class AtomosLauncher extends FrameworkLauncher {
     @Override
     public void prepare(LauncherPrepareContext launcherPrepareContext, 
ArtifactId artifactId, Feature feature) throws Exception {
@@ -73,6 +53,7 @@ public class AtomosLauncher extends FrameworkLauncher {
         return AtomosRunner.class.getName();
     }
 
+    /*
     @Override
     public LauncherClassLoader createClassLoader() {
         return LOADER;
@@ -145,4 +126,5 @@ public class AtomosLauncher extends FrameworkLauncher {
             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
index 7edf1530..6ac477ef 100644
--- 
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
@@ -18,32 +18,9 @@
  
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 package org.apache.sling.feature.launcher.atomos;
 
-import org.apache.felix.atomos.Atomos;
-import org.apache.felix.atomos.AtomosContent;
-import org.apache.felix.atomos.AtomosLayer;
-import org.apache.felix.atomos.impl.base.AtomosBase;
-import org.apache.felix.framework.BundleWiringImpl;
-import org.apache.sling.feature.ArtifactId;
-import org.apache.sling.feature.io.IOUtils;
-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.BundleReference;
-import org.osgi.framework.Constants;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.Version;
-import org.osgi.framework.connect.ConnectContent;
-import org.osgi.framework.connect.FrameworkUtilHelper;
-import org.osgi.framework.launch.Framework;
-import org.osgi.framework.launch.FrameworkFactory;
-import org.osgi.framework.startlevel.BundleStartLevel;
-
-import javax.swing.text.html.Option;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLConnection;
 import java.net.URLStreamHandler;
@@ -58,11 +35,26 @@ import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.BiConsumer;
 
+import org.apache.felix.atomos.Atomos;
+import org.apache.felix.atomos.AtomosContent;
+import org.apache.felix.atomos.impl.base.AtomosBase;
+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.BundleReference;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.connect.ConnectContent;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.launch.FrameworkFactory;
+import org.osgi.framework.startlevel.BundleStartLevel;
+
 public class AtomosRunner extends FrameworkRunner {
 
     private static final ConcurrentHashMap<String, ClassLoader> 
location2Loader = new ConcurrentHashMap<>();
     private static final ConcurrentHashMap<String, Bundle> classToBundle = new 
ConcurrentHashMap<>();
-    private static final Atomos m_atomos = Atomos.newAtomos();
+    private static Atomos m_atomos;
     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 {
@@ -79,6 +71,13 @@ public class AtomosRunner extends FrameworkRunner {
         return result;
     }
 
+    private synchronized static Atomos getAtomos() {
+        if (m_atomos == null) {
+            m_atomos = Atomos.newAtomos();
+        }
+        return m_atomos;
+    }
+
     private static int getProperty(BundleContext bc, String propName, int 
defaultValue) {
         String val = bc.getProperty(propName);
         if (val == null) {
@@ -90,7 +89,7 @@ public class AtomosRunner extends FrameworkRunner {
 
     @Override
     protected FrameworkFactory getFrameworkFactory() throws Exception {
-        return new AtomosFrameworkFactory(m_atomos);
+        return new AtomosFrameworkFactory(getAtomos());
     }
 
     @Override
@@ -121,16 +120,12 @@ public class AtomosRunner extends FrameworkRunner {
     private void install(final Framework framework, final Map<Integer, 
List<URL>> bundleMap) throws BundleException {
         System.out.println(System.getProperty("java.specification.version"));
         final BundleContext bc = framework.getBundleContext();
-        System.out.println(bc.getBundle(0).getHeaders());
+        // System.out.println(bc.getBundle(0).getHeaders());
         int defaultStartLevel = getProperty(bc, "felix.startlevel.bundle", 1);
 
         System.out.println(new File(".").getAbsolutePath());
         System.out.println(new File(new File("."), 
"content").getAbsolutePath());
 
-        /*for (File child : new File(new File("."), "content").listFiles()) {
-            System.out.println(child.getAbsolutePath());
-        }*/
-
         for (final Integer startLevel : sortStartLevels(bundleMap.keySet(), 
defaultStartLevel)) {
             logger.debug("Installing bundles with start level {}", startLevel);
 
@@ -144,7 +139,7 @@ public class AtomosRunner extends FrameworkRunner {
                     }
                 };
 
-                AtomosContent content = m_atomos
+                AtomosContent content = getAtomos()
                         .getBootLayer()
                         .getAtomosContents().stream()
                         .filter(atomosContent -> {
@@ -215,11 +210,19 @@ public class AtomosRunner extends FrameworkRunner {
     }
 
     public static InputStream getAtomosLoaderStreamWrapped(Class origin, 
String resource) {
-        return 
getAtomosLoaderWrapped(origin).getResourceAsStream(resolveName(origin, 
resource));
+        URL u = getAtomosLoaderWrapped(origin).getResource(resolveName(origin, 
resource));
+        if (u == null) {
+            return null;
+        }
+
+        try {
+            return u.openStream();
+        } catch (IOException e) {
+            return null;
+        }
     }
 
     public static ClassLoader getAtomosLoaderWrapped(Class origin) {
-        System.out.println("TRAP: " + origin.getName());
         if (origin.isInterface()) {
             return origin.getClassLoader();
         }
@@ -229,7 +232,7 @@ public class AtomosRunner extends FrameworkRunner {
             } catch (Throwable ex) {
                 return null;
             }});
-        System.out.println(bundle);
+
         return Optional.ofNullable(bundle).map(b ->
                     location2Loader.computeIfAbsent(b.getLocation(), location 
-> new BundleClassLoader(origin, bundle) )
                 ).orElseGet(origin::getClassLoader);
@@ -264,6 +267,20 @@ public class AtomosRunner extends FrameworkRunner {
             return result != null ? result : Collections.emptyEnumeration();
         }
 
+        @Override
+        public InputStream getResourceAsStream(String name) {
+            URL u = getResource(name);
+            if (u == null) {
+                return null;
+            }
+
+            try {
+                return u.openStream();
+            } catch (IOException e) {
+                return null;
+            }
+        }
+
         @Override
         public Bundle getBundle() {
             return bundle;
diff --git a/atomosfeaturelauncherconfig/pom.xml 
b/atomosfeaturelauncherconfig/pom.xml
index 7da4a115..832705fc 100644
--- a/atomosfeaturelauncherconfig/pom.xml
+++ b/atomosfeaturelauncherconfig/pom.xml
@@ -107,6 +107,11 @@
             <artifactId>org.apache.felix.atomos.utils.core</artifactId>
             <version>0.9.1-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            
<artifactId>org.apache.sling.feature.launcher.atomos.weaver</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
     </dependencies>
 
 </project>
diff --git 
a/atomosfeaturelauncherconfig/src/main/java/org/apache/sling/feature/launcher/atomos/config/AtomosConfigLauncher.java
 
b/atomosfeaturelauncherconfig/src/main/java/org/apache/sling/feature/launcher/atomos/config/AtomosConfigLauncher.java
index ce45e95e..45f90230 100644
--- 
a/atomosfeaturelauncherconfig/src/main/java/org/apache/sling/feature/launcher/atomos/config/AtomosConfigLauncher.java
+++ 
b/atomosfeaturelauncherconfig/src/main/java/org/apache/sling/feature/launcher/atomos/config/AtomosConfigLauncher.java
@@ -18,6 +18,38 @@
  
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 package org.apache.sling.feature.launcher.atomos.config;
 
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.zip.ZipException;
+
+import javax.json.Json;
+import javax.json.JsonObject;
+import javax.json.JsonString;
+import javax.script.ScriptEngineManager;
+
 import org.apache.felix.atomos.utils.api.plugin.SubstratePlugin;
 import org.apache.felix.atomos.utils.core.LauncherBuilderImpl;
 import 
org.apache.felix.atomos.utils.substrate.api.resource.ResourceConfiguration;
@@ -28,14 +60,14 @@ import org.apache.felix.scr.impl.logger.BundleLogger;
 import org.apache.sling.feature.Artifact;
 import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.Extension;
-import org.apache.sling.feature.ExtensionState;
-import org.apache.sling.feature.ExtensionType;
 import org.apache.sling.feature.Feature;
 import org.apache.sling.feature.builder.BuilderContext;
 import org.apache.sling.feature.builder.FeatureBuilder;
 import org.apache.sling.feature.builder.FeatureProvider;
 import org.apache.sling.feature.io.IOUtils;
 import org.apache.sling.feature.io.json.FeatureJSONReader;
+import org.apache.sling.feature.io.json.FeatureJSONWriter;
+import org.apache.sling.feature.launcher.atomos.weaver.AtomosWeaver;
 import org.apache.sling.feature.launcher.impl.launchers.FrameworkLauncher;
 import org.apache.sling.feature.launcher.spi.LauncherPrepareContext;
 import org.apache.sling.feature.launcher.spi.LauncherRunContext;
@@ -44,27 +76,26 @@ import org.osgi.util.converter.Converter;
 import org.osgi.util.function.Function;
 import org.slf4j.LoggerFactory;
 
-import javax.json.Json;
-import javax.json.JsonObject;
-import javax.json.JsonString;
-import javax.json.JsonStructure;
-import javax.script.ScriptEngineManager;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.StringReader;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Paths;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
 public class AtomosConfigLauncher extends FrameworkLauncher {
 
     private volatile Feature m_app;
+    private final AtomosWeaver m_weaver;
+
+    public AtomosConfigLauncher() {
+        m_weaver = getWeaver();
+
+        if (m_weaver == null) {
+            throw new IllegalStateException("AtomosWeaver not found via 
ServiceLoader");
+        }
+    }
+
+    private static AtomosWeaver getWeaver() {
+        Iterator<AtomosWeaver> loader = 
ServiceLoader.load(AtomosWeaver.class).iterator();
+        if (loader.hasNext()) {
+            return loader.next();
+        }
+        return null;
+    }
 
     @Override
     public void prepare(final LauncherPrepareContext context,
@@ -108,53 +139,240 @@ public class AtomosConfigLauncher extends 
FrameworkLauncher {
         m_app = app;
     }
 
+    private JarOutputStream getJarToBuild(File inJar, File outJar) throws 
IOException {
+        try(JarFile srcJar = new JarFile(inJar)) {
+            JarOutputStream destJar = new JarOutputStream(new 
FileOutputStream(outJar), srcJar.getManifest());
+
+            for(JarEntry entry : Collections.list(srcJar.entries())) {
+                if ("META-INF/MANIFEST.MF".equals(entry.getName())) {
+                    continue;
+                }
+
+                destJar.putNextEntry(entry);
+                InputStream is = srcJar.getInputStream(entry);
+                is.transferTo(destJar);
+                destJar.closeEntry();
+            }
+
+            return destJar;
+        }
+    }
+
+    private void addClassesToJar(String jarFileName, JarOutputStream outJar, 
ClassLoader cl) throws IOException {
+        try (JarFile jf = new JarFile(jarFileName)) {
+            for (JarEntry entry : Collections.list(jf.entries())) {
+                String fileName = entry.getName();
+
+                // only add class entries.
+                if (!fileName.endsWith(".class") &&
+                    !fileName.endsWith(".properties")) {  // The .properties 
files are included here until we have weave ResourceBundle invocations
+                    continue;
+                }
+
+                if (fileName.endsWith("module-info.class")) {
+                    continue;
+                }
+
+                try {
+                    JarEntry newEntry = new JarEntry(entry.getName());
+                    outJar.putNextEntry(newEntry);
+                    InputStream is = jf.getInputStream(entry);
+
+                    if (fileName.endsWith(".class")) {
+                        // Weave the class bytes and then write them to the 
target jar
+                        String className = fileName.substring(0, 
fileName.length() - 6).replace('/', '.');
+                        byte[] classBytes = is.readAllBytes();
+
+                        try {
+                            byte[] woven = m_weaver.weave(classBytes, 
"org.apache.sling.feature.launcher.atomos.AtomosRunner",
+                                "getAtomosLoaderWrapped", 
"getAtomosLoaderResourceWrapped", "getAtomosLoaderStreamWrapped", cl);
+                            outJar.write(woven);
+                        } catch (Exception ex) {
+                            System.out.println("\nProblem weaving " + 
className + " " + ex.getMessage());
+                            // Use unwoven bytes
+                            outJar.write(classBytes);
+                        }
+                    } else {
+                        // It's not a class file, don't try to weave
+                        is.transferTo(outJar);
+                    }
+                    outJar.closeEntry();
+                } catch (ZipException ze) {
+                    // Happens in case of a duplicate class file.
+                    System.out.println("Warn: " + ze.getMessage());
+
+                    continue;
+                }
+            }
+        }
+    }
+
+    private void addNativeImageProperties(JarOutputStream jarToBuild, String 
iabt) throws IOException {
+        String iart = "--initialize-at-run-time=" +
+            "org.owasp.esapi.reference.DefaultValidator," +
+            "org.owasp.esapi.reference.JavaLogFactory$JavaLogger";
+
+        iabt += ",org.apache.sling.feature.launcher.atomos.AtomosRunner";
+
+        JarEntry je = new 
JarEntry("META-INF/native-image/app/native-image.properties");
+        jarToBuild.putNextEntry(je);
+        String args = "Args = " + iabt + " " + iart + System.lineSeparator();
+        jarToBuild.write(args.getBytes());
+        jarToBuild.closeEntry();
+    }
+
+    private List<String> extractBundleClassPathJars(List<String> jars, File 
targetDir) throws IOException {
+        targetDir.mkdirs();
+        List<String> result = new ArrayList<>();
+
+        for (String jar : jars) {
+            File file = new File(jar);
+            try (JarFile jf = new JarFile(file)) {
+                Manifest mf = jf.getManifest();
+                Attributes ma = mf.getMainAttributes();
+                String bcp = ma.getValue("Bundle-ClassPath");
+
+                if (bcp == null) {
+                    continue;
+                }
+
+                for (String embedded : bcp.split(",")) {
+                    JarEntry entry = jf.getJarEntry(embedded);
+                    if (entry == null) {
+                        continue;
+                    }
+
+                    File tDir = new File(targetDir, file.getName());
+                    tDir.mkdirs();
+                    File tFile = new File(tDir, entry.getName());
+
+                    try (InputStream is = jf.getInputStream(entry);
+                        OutputStream os = new FileOutputStream(tFile)) {
+                        is.transferTo(os);
+                    }
+                    result.add(tFile.getAbsolutePath());
+                }
+            }
+        }
+
+        return result;
+    }
+
     @Override
     public int run(LauncherRunContext context, ClassLoader cl) throws 
Exception {
         int result = super.run(context, cl);
         if (result == FrameworkEvent.STOPPED) {
             File outputDir = new File(Paths.get("").toAbsolutePath().toFile(), 
"atomos-config");
             outputDir.mkdirs();
-            try (Reader reader = new FileReader(new File(outputDir, 
"config-feature.slingosgifeature"), StandardCharsets.UTF_8)) {
-                Feature config = FeatureJSONReader.read(reader, null);
-                Feature assembled = 
FeatureBuilder.assemble(ArtifactId.parse("config:assembled:1.0.0"), new 
BuilderContext(new FeatureProvider() {
-                    @Override
-                    public Feature provide(ArtifactId id) {
-                        return null;
-                    }
-                }), m_app, config);
-                Extension assembledEx = 
assembled.getExtensions().getByName("atomos-config");
-                JsonObject nativeConfig = 
assembledEx.getJSONStructure().asJsonObject();
-                write(outputDir, "reflect-config", nativeConfig);
-                write(outputDir, "resource-config", nativeConfig);
-                write(outputDir, "proxy-config", nativeConfig);
-                write(outputDir, "jni-config", nativeConfig);
-                write(outputDir, "serialization-config", nativeConfig);
-
-                try (FileOutputStream output = new FileOutputStream(new 
File(outputDir,  "atomos_init.sh"))) {
-                    String script = "#!/bin/sh\n\nexport ATOMOS_CLASSPATH=\"";
-                    if (nativeConfig.containsKey("classpath")) {
-                        script += 
nativeConfig.getJsonArray("classpath").getValuesAs(JsonString.class).stream().map(JsonString::getString).collect(Collectors.joining(":"));
-                    }
-                    script += "\"\n\nexport ATOMOS_INIT=\"";
-                    if (nativeConfig.containsKey("initialize-at-build-time")) {
-                        script += "--initialize-at-build-time=" + 
nativeConfig.getJsonArray("initialize-at-build-time").getValuesAs(JsonString.class).stream().map(JsonString::getString).collect(Collectors.joining(","));
+
+            try (JarOutputStream jarToBuild = getJarToBuild(new 
File(outputDir, "atomos.substrate.jar"), new File(outputDir, 
"app.substrate.jar"))) {
+                try (Reader reader = new FileReader(new File(outputDir, 
"config-feature.slingosgifeature"), StandardCharsets.UTF_8)) {
+                    Feature config = FeatureJSONReader.read(reader, null);
+                    Feature assembled = 
FeatureBuilder.assemble(ArtifactId.parse("config:assembled:1.0.0"), new 
BuilderContext(new FeatureProvider() {
+                        @Override
+                        public Feature provide(ArtifactId id) {
+                            return null;
+                        }
+                    }), m_app, config);
+                    Extension assembledEx = 
assembled.getExtensions().getByName("atomos-config");
+                    JsonObject nativeConfig = 
assembledEx.getJSONStructure().asJsonObject();
+                    write(outputDir, jarToBuild, "reflect-config", 
nativeConfig);
+                    write(outputDir, jarToBuild, "resource-config", 
nativeConfig);
+                    write(outputDir, jarToBuild, "proxy-config", nativeConfig);
+                    write(outputDir, jarToBuild, "jni-config", nativeConfig);
+                    write(outputDir, jarToBuild, "serialization-config", 
nativeConfig);
+
+                    try (FileOutputStream output = new FileOutputStream(new 
File(outputDir,  "atomos_init.sh"))) {
+                        String script = "#!/bin/sh\n\nexport 
ATOMOS_CLASSPATH=\"";
+                        if (nativeConfig.containsKey("classpath")) {
+                            script += 
nativeConfig.getJsonArray("classpath").getValuesAs(JsonString.class).stream().map(JsonString::getString).collect(Collectors.joining(":"));
+
+                            extractJarsAndCollect(nativeConfig, jarToBuild, 
outputDir);
+                        }
+                        script += "\"\n\nexport ATOMOS_INIT=\"";
+                        if 
(nativeConfig.containsKey("initialize-at-build-time")) {
+                            String iabt = "--initialize-at-build-time=" + 
nativeConfig.getJsonArray("initialize-at-build-time").getValuesAs(JsonString.class).stream().map(JsonString::getString).collect(Collectors.joining(","));
+                            script += iabt;
+
+                            // Add the initialize at build time to a 
native-image.properties file
+                            addNativeImageProperties(jarToBuild, iabt);
+                        }
+                        script += "\"\n";
+                        output.write(script.getBytes(StandardCharsets.UTF_8));
                     }
-                    script += "\"\n";
-                    output.write(script.getBytes(StandardCharsets.UTF_8));
+
+                    addFeatureToJar(jarToBuild);
+                } catch (Throwable t) {
+                    t.printStackTrace();
+                    throw t;
                 }
-            } catch (Throwable t) {
-                t.printStackTrace();
-                throw t;
             }
-
         }
+
+        /* */ System.out.println("*** Finished");
+        System.exit(0);
         return result;
     }
 
-    private void write(File outputDir, String name, JsonObject source) throws 
IOException {
+    private void addFeatureToJar(JarOutputStream jarToBuild) throws 
IOException {
+        JarEntry je = new JarEntry("META-INF/features/feature.json");
+        jarToBuild.putNextEntry(je);
+        try (Writer wr = new OutputStreamWriter(jarToBuild)) {
+            FeatureJSONWriter.write(wr, m_app);
+        }
+    }
+
+    private void extractJarsAndCollect(JsonObject nativeConfig, 
JarOutputStream jarToBuild, File outputDir) throws IOException {
+        List<String> jarsToBeCleaned = 
nativeConfig.getJsonArray("classpath").getValuesAs(JsonString.class).stream().map(JsonString::getString).collect(Collectors.toList());
+        List<String> jars = jarsToBeCleaned.stream()
+            .filter(n -> !n.equals("atomos.substrate.jar"))
+            .filter(n -> !n.contains("org.apache.felix.framework-"))
+            .collect(Collectors.toList());
+
+        List<String> bcpJars = extractBundleClassPathJars(jars, new 
File(outputDir, "../bcpJars"));
+        jars.addAll(bcpJars);
+
+        List<URL> jarURLs = 
nativeConfig.getJsonArray("classpath").getValuesAs(JsonString.class).stream().map(JsonString::getString)
+            .map(j -> {
+                try {
+                    return new File(j).toURI().toURL();
+                } catch (Exception ex) {
+                    throw new RuntimeException(ex);
+                }}).collect(Collectors.toList());
+        List<URL> bcpJarURLs = bcpJars.stream().map(j -> {
+                try {
+                    return new File(j).toURI().toURL();
+                } catch (Exception ex) {
+                    throw new RuntimeException(ex);
+                }}).collect(Collectors.toList());
+        jarURLs.addAll(bcpJarURLs);
+
+        List<URL> clURLs = new ArrayList<>(jarURLs);
+        // Temp hack for the 
org.owasp.esapi.reference.DefaultSecurityConfiguration which references 
(imports)
+        // an antiquated commons-lang class but doesn't use it through the 
code path we are executing.
+        // It also doesn't import it on the OSGi level.
+        clURLs.add(new 
URL("https://repo.maven.apache.org/maven2/commons-lang/commons-lang/2.6/commons-lang-2.6.jar";));
+        URLClassLoader jarCL = new URLClassLoader(clURLs.toArray(new URL[0]));
+
+        for (String jar : jars) {
+            try {
+            addClassesToJar(jar, jarToBuild, jarCL);
+            } catch (Exception e) {
+                e.printStackTrace();
+                System.exit(-1);
+            }
+        }
+    }
+
+    private void write(File outputDir, JarOutputStream outputJar, String name, 
JsonObject source) throws IOException {
         try (FileOutputStream output = new FileOutputStream(new 
File(outputDir, name + ".json"))) {
             if (source.containsKey(name)) {
                 Json.createWriter(output).write(source.get(name));
+
+                JarEntry je = new JarEntry("META-INF/native-image/app/" + name 
+ ".json");
+
+                outputJar.putNextEntry(je);
+                Json.createWriter(outputJar).write(source.get(name));
             }
         }
     }
diff --git 
a/atomosfeaturelauncherconfig/src/main/java/org/apache/sling/feature/launcher/atomos/config/IndexPlugin.java
 
b/atomosfeaturelauncherconfig/src/main/java/org/apache/sling/feature/launcher/atomos/config/IndexPlugin.java
index 176d0f93..fff1fbf4 100644
--- 
a/atomosfeaturelauncherconfig/src/main/java/org/apache/sling/feature/launcher/atomos/config/IndexPlugin.java
+++ 
b/atomosfeaturelauncherconfig/src/main/java/org/apache/sling/feature/launcher/atomos/config/IndexPlugin.java
@@ -18,20 +18,8 @@
  
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 package org.apache.sling.feature.launcher.atomos.config;
 
-import org.apache.felix.atomos.utils.api.Context;
-import org.apache.felix.atomos.utils.api.FileType;
-import org.apache.felix.atomos.utils.api.IndexInfo;
-import org.apache.felix.atomos.utils.api.plugin.JarPlugin;
-import org.apache.felix.atomos.utils.core.IndexInfoImpl;
-import org.apache.felix.atomos.utils.core.plugins.index.IndexOutputType;
-import org.apache.felix.atomos.utils.core.plugins.index.IndexPluginConfig;
-import 
org.apache.felix.atomos.utils.substrate.impl.config.DefaultResourceConfiguration;
-import org.apache.felix.atomos.utils.substrate.impl.json.ResourceJsonUtil;
-import org.osgi.framework.Constants;
-
 import java.io.BufferedWriter;
 import java.io.ByteArrayOutputStream;
-import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStreamWriter;
@@ -56,6 +44,17 @@ import java.util.jar.JarOutputStream;
 import java.util.jar.Manifest;
 import java.util.stream.Collectors;
 
+import org.apache.felix.atomos.utils.api.Context;
+import org.apache.felix.atomos.utils.api.FileType;
+import org.apache.felix.atomos.utils.api.IndexInfo;
+import org.apache.felix.atomos.utils.api.plugin.JarPlugin;
+import org.apache.felix.atomos.utils.core.IndexInfoImpl;
+import org.apache.felix.atomos.utils.core.plugins.index.IndexOutputType;
+import org.apache.felix.atomos.utils.core.plugins.index.IndexPluginConfig;
+import 
org.apache.felix.atomos.utils.substrate.impl.config.DefaultResourceConfiguration;
+import org.apache.felix.atomos.utils.substrate.impl.json.ResourceJsonUtil;
+import org.osgi.framework.Constants;
+
 public class IndexPlugin implements JarPlugin<IndexPluginConfig> {
     private static final String ATOMOS_BUNDLE_SEPARATOR = "ATOMOS_BUNDLE";
 
@@ -93,6 +92,7 @@ public class IndexPlugin implements 
JarPlugin<IndexPluginConfig> {
 
     @Override
     public void initJar(JarFile jar, Context context, URLClassLoader 
classLoader) {
+        /*
         // Detect if there are duplicates using the uniquePaths map
         jar.stream().filter(this::include).forEach(e -> uniquePaths.compute(
                 e.getName(),
@@ -106,6 +106,11 @@ public class IndexPlugin implements 
JarPlugin<IndexPluginConfig> {
                                 || b != null //
                                 ? Boolean.FALSE
                                 : Boolean.TRUE));
+        */
+
+        jar.stream().filter(this::include).forEach(e -> uniquePaths.compute(
+                e.getName(),
+                (p, b) ->  Boolean.FALSE));
     }
 
     @Override
diff --git 
a/atomosfeaturelauncherweaver/src/main/java/org/apache/sling/feature/launcher/atomos/weaver/impl/AtomosWeaverVisitor.java
 
b/atomosfeaturelauncherweaver/src/main/java/org/apache/sling/feature/launcher/atomos/weaver/impl/AtomosWeaverVisitor.java
index 349fd8ba..cc072270 100644
--- 
a/atomosfeaturelauncherweaver/src/main/java/org/apache/sling/feature/launcher/atomos/weaver/impl/AtomosWeaverVisitor.java
+++ 
b/atomosfeaturelauncherweaver/src/main/java/org/apache/sling/feature/launcher/atomos/weaver/impl/AtomosWeaverVisitor.java
@@ -18,20 +18,19 @@
  
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 package org.apache.sling.feature.launcher.atomos.weaver.impl;
 
+import java.io.InputStream;
+import java.net.URL;
+
 import org.objectweb.asm.ClassReader;
 import org.objectweb.asm.ClassVisitor;
 import org.objectweb.asm.ClassWriter;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
-
 import org.objectweb.asm.Type;
 import org.objectweb.asm.commons.GeneratorAdapter;
 import org.objectweb.asm.commons.JSRInlinerAdapter;
 import org.objectweb.asm.commons.Method;
 
-import java.io.InputStream;
-import java.net.URL;
-
 public class AtomosWeaverVisitor  extends ClassVisitor implements Opcodes {
     public static byte[] weave(byte[] bytes, String targetClass, String 
targetMethodClassLoader, String targetMethodResource, String 
targetMethodStream, ClassLoader cl) {
         ClassReader cr = new ClassReader(bytes);
@@ -44,10 +43,12 @@ public class AtomosWeaverVisitor  extends ClassVisitor 
implements Opcodes {
             ),new Method(targetMethodResource,
                 Type.getType(URL.class),
                 new Type[] 
{Type.getType(Class.class),Type.getType(String.class)}
-        ),new Method(targetMethodStream,
+            ),new Method(targetMethodStream,
                 Type.getType(InputStream.class),
                 new Type[] {Type.getType(Class.class), 
Type.getType(String.class)}
-        )
+            ),new Method("getEntry",
+                Type.getType(URL.class),
+                new Type[] {Type.getType(String.class)}        )
         );
         cr.accept(cv, ClassReader.SKIP_FRAMES);
         if (cv.isWoven()) {
@@ -62,13 +63,15 @@ public class AtomosWeaverVisitor  extends ClassVisitor 
implements Opcodes {
     private final Method targetMethodClassLoader;
     private final Method targetMethodResource;
     private final Method targetMethodStream;
+    private final Method targetMethodBundleResource;
 
-    AtomosWeaverVisitor(ClassWriter cv, Type target, Method 
targetMethodClassLoader, Method targetMethodResource, Method 
targetMethodStream) {
+    AtomosWeaverVisitor(ClassWriter cv, Type target, Method 
targetMethodClassLoader, Method targetMethodResource, Method 
targetMethodStream, Method targetMethodBundleResource) {
         super(Opcodes.ASM9, cv);
         this.target = target;
         this.targetMethodClassLoader = targetMethodClassLoader;
         this.targetMethodResource = targetMethodResource;
         this.targetMethodStream = targetMethodStream;
+        this.targetMethodBundleResource = targetMethodBundleResource;
     }
 
     boolean isWoven() {
@@ -109,6 +112,14 @@ public class AtomosWeaverVisitor  extends ClassVisitor 
implements Opcodes {
                     return;
                 }
             }
+
+            if (opcode == INVOKEINTERFACE && owner.replace('/', 
'.').equals("org.osgi.framework.Bundle")) {
+                if (name.equals("getResource")) {
+                    invokeInterface(Type.getType("L" + owner.replace('.', '/') 
+ ";"), targetMethodBundleResource);
+                    m_woven = true;
+                    return;
+                }
+            }
             super.visitMethodInsn(opcode, owner, name, desc, itf);
         }
     }


Reply via email to