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 <[email protected]>
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);
}
}