in arthur-maven-plugin/src/main/java/org/apache/geronimo/arthur/maven/mojo/NativeImageMojo.java [384:530]
public void execute() {
if (skip) {
getLog().info("Skipping execution as requested");
return;
}
if ("pom".equals(packaging)) {
getLog().info("Skipping packaging pom");
return;
}
final Map<Artifact, Path> classpathEntries = findClasspathFiles().collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a));
final ArthurNativeImageConfiguration configuration = getConfiguration(classpathEntries.values());
configuration.complete(graalVersion, classpathEntries.values().stream()
.anyMatch(p -> {
if (Files.isDirectory(p)) {
return Files.exists(p.resolve("META-INF/native-image"));
}
if (Files.exists(p)) {
try (final JarFile jar = new JarFile(p.toFile())) {
final ZipEntry entry = jar.getEntry("META-INF/native-image");
return entry != null && entry.isDirectory();
} catch (final IOException e) {
return false;
}
}
return false;
}));
if (nativeImage == null) {
final SdkmanGraalVMInstaller graalInstaller = createInstaller();
final Path graalHome = graalInstaller.install();
getLog().info("Using GRAAL: " + graalHome);
configuration.setNativeImage(graalInstaller.installNativeImage().toAbsolutePath().toString());
}
final URL[] urls = classpathEntries.values().stream()
.map(it -> {
try {
return it.toUri().toURL();
} catch (final MalformedURLException e) {
throw new IllegalStateException(e);
}
}).toArray(URL[]::new);
final Thread thread = Thread.currentThread();
final ClassLoader parentLoader = useTcclAsScanningParentClassLoader ?
thread.getContextClassLoader() : getSystemClassLoader();
final ClassLoader oldLoader = thread.getContextClassLoader();
if (getLog().isDebugEnabled()) {
getLog().debug("Classpath:\n" + Stream.of(urls).map(URL::toExternalForm).collect(joining("\n")));
}
try (final URLClassLoader loader = new URLClassLoader(urls, parentLoader) {
@Override
protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
if (name != null) {
if (name.startsWith("org.")) {
final String org = name.substring("org.".length());
if (org.startsWith("slf4j.")) {
return oldLoader.loadClass(name);
}
if (org.startsWith("apache.geronimo.arthur.")) {
final String arthur = org.substring("apache.geronimo.arthur.".length());
if (arthur.startsWith("api.") || arthur.startsWith("spi") || arthur.startsWith("impl")) {
return oldLoader.loadClass(name);
}
}
}
}
return super.loadClass(name, resolve);
}
}; final Jsonb jsonb = JsonbBuilder.create(new JsonbConfig()
.setProperty("johnzon.cdi.activated", false)
.withPropertyOrderStrategy(PropertyOrderStrategy.LEXICOGRAPHICAL))) {
thread.setContextClassLoader(loader);
final Predicate<Artifact> scanningFilter = createScanningFilter();
final Function<Archive, Archive> archiveProcessor = createArchiveFilter();
final AnnotationFinder finder = new AnnotationFinder(archiveProcessor.apply(new CompositeArchive(classpathEntries.entrySet().stream()
.filter(e -> scanningFilter.test(e.getKey()))
.map(Map.Entry::getValue)
.map(path -> {
try {
return archive(loader, path.toUri().toURL());
} catch (final MalformedURLException e) { // unlikely
throw new IllegalStateException(e);
}
})
.collect(toList()))));
final AtomicBoolean finderLinked = new AtomicBoolean();
MavenArthurExtension.with(
reflections, resources, bundles, dynamicProxies,
() -> new ArthurNativeImageExecutor(
ArthurNativeImageExecutor.ExecutorConfiguration.builder()
.jsonSerializer(jsonb::toJson)
.annotatedClassFinder(finder::findAnnotatedClasses)
.annotatedFieldFinder(finder::findAnnotatedFields)
.annotatedMethodFinder(finder::findAnnotatedMethods)
.extensionProperties(getExtensionProperties())
.implementationFinder(p -> {
if (finderLinked.compareAndSet(false, true)) {
finder.enableFindImplementations().enableFindSubclasses();
}
final Class parent = Class.class.cast(p);
final List<Class<?>> implementations = finder.findImplementations(parent);
final List<Class<?>> subclasses = finder.findSubclasses(parent);
if (implementations.size() + subclasses.size() == 0) {
return implementations; // empty
}
final List<Class<?>> output = new ArrayList<>(implementations.size() + subclasses.size());
output.addAll(implementations);
output.addAll(subclasses);
return output;
})
.configuration(configuration)
.workingDirectory(workdir.toPath().resolve("generated_configuration"))
.build()) {
@Override
protected Iterable<ArthurExtension> loadExtensions() {
return Stream.concat(
// classloading bypasses them since TCCL is a fake loader with the JVM as parent
Stream.of(new AnnotationExtension(), new MavenArthurExtension()),
// graalextensions
StreamSupport.stream(super.loadExtensions().spliterator(), false))
// ensure we dont duplicate any extension
.distinct()
.sorted(comparing(ArthurExtension::order))
.collect(toList());
}
}
.run());
} catch (final Exception e) {
throw new IllegalStateException(e);
} finally {
thread.setContextClassLoader(oldLoader);
}
if (propertiesPrefix != null) {
project.getProperties().setProperty(propertiesPrefix + "binary.path", output);
}
if (attach) {
if (!"none".equals(attachClassifier) && attachClassifier != null && !attachClassifier.isEmpty()) {
helper.attachArtifact(project, attachType, attachClassifier, new File(output));
} else {
helper.attachArtifact(project, attachType, new File(output));
}
}
}