Skip to content

Commit

Permalink
Merge pull request #34828 from gsmet/3.2.1-backports-2
Browse files Browse the repository at this point in the history
3.2.1 backports 2
  • Loading branch information
gsmet authored Jul 19, 2023
2 parents 80c2c5a + 238c259 commit 9e6b6e8
Show file tree
Hide file tree
Showing 128 changed files with 2,688 additions and 1,404 deletions.
8 changes: 4 additions & 4 deletions bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
<microprofile-rest-client.version>3.0.1</microprofile-rest-client.version>
<microprofile-jwt.version>2.1</microprofile-jwt.version>
<microprofile-lra.version>2.0</microprofile-lra.version>
<microprofile-openapi.version>3.1</microprofile-openapi.version>
<microprofile-openapi.version>3.1.1</microprofile-openapi.version>
<smallrye-common.version>2.1.0</smallrye-common.version>
<smallrye-config.version>3.3.0</smallrye-config.version>
<smallrye-health.version>4.0.2</smallrye-health.version>
Expand All @@ -63,7 +63,7 @@
<smallrye-graphql.version>2.2.1</smallrye-graphql.version>
<smallrye-opentracing.version>3.0.3</smallrye-opentracing.version>
<smallrye-fault-tolerance.version>6.2.4</smallrye-fault-tolerance.version>
<smallrye-jwt.version>4.2.1</smallrye-jwt.version>
<smallrye-jwt.version>4.3.0</smallrye-jwt.version>
<smallrye-context-propagation.version>2.1.0</smallrye-context-propagation.version>
<smallrye-reactive-streams-operators.version>1.0.13</smallrye-reactive-streams-operators.version>
<smallrye-reactive-types-converter.version>3.0.0</smallrye-reactive-types-converter.version>
Expand Down Expand Up @@ -102,7 +102,7 @@
<hibernate-orm.version>6.2.6.Final</hibernate-orm.version>
<bytebuddy.version>1.12.18</bytebuddy.version> <!-- Version controlled by Hibernate ORM's needs -->
<hibernate-commons-annotations.version>6.0.6.Final</hibernate-commons-annotations.version> <!-- version controlled by Hibernate ORM -->
<hibernate-reactive.version>2.0.2.Final</hibernate-reactive.version>
<hibernate-reactive.version>2.0.3.Final</hibernate-reactive.version>
<hibernate-validator.version>8.0.1.Final</hibernate-validator.version>
<hibernate-search.version>6.1.7.Final</hibernate-search.version>
<narayana.version>6.0.1.Final</narayana.version>
Expand Down Expand Up @@ -218,7 +218,7 @@
<strimzi-oauth.nimbus.version>9.31</strimzi-oauth.nimbus.version>
<java-buildpack-client.version>0.0.6</java-buildpack-client.version>
<org-crac.version>0.1.3</org-crac.version>
<sshd-common.version>2.9.2</sshd-common.version>
<sshd-common.version>2.10.0</sshd-common.version>
<mime4j.version>0.8.9</mime4j.version>
<mutiny-zero.version>1.0.0</mutiny-zero.version>
<!-- Dev UI -->
Expand Down
101 changes: 65 additions & 36 deletions core/deployment/src/main/java/io/quarkus/deployment/CodeGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,18 @@ public class CodeGenerator {

private static final Logger log = Logger.getLogger(CodeGenerator.class);

private static final List<String> CONFIG_SOURCE_FACTORY_INTERFACES = List.of(
"META-INF/services/io.smallrye.config.ConfigSourceFactory",
"META-INF/services/org.eclipse.microprofile.config.spi.ConfigSourceProvider");
private static final String META_INF_SERVICES = "META-INF/services/";

private static final List<String> CONFIG_SERVICES = List.of(
"org.eclipse.microprofile.config.spi.Converter",
"org.eclipse.microprofile.config.spi.ConfigSource",
"org.eclipse.microprofile.config.spi.ConfigSourceProvider",
"io.smallrye.config.ConfigSourceInterceptor",
"io.smallrye.config.ConfigSourceInterceptorFactory",
"io.smallrye.config.ConfigSourceFactory",
"io.smallrye.config.SecretKeysHandler",
"io.smallrye.config.SecretKeysHandlerFactory",
"io.smallrye.config.ConfigValidator");

// used by Gradle and Maven
public static void initAndRun(QuarkusClassLoader classLoader,
Expand Down Expand Up @@ -178,18 +187,18 @@ public static boolean trigger(ClassLoader deploymentClassLoader,

public static Config getConfig(ApplicationModel appModel, LaunchMode launchMode, Properties buildSystemProps,
QuarkusClassLoader deploymentClassLoader) throws CodeGenException {
// Config instance that is returned by this method should be as close to the one built in the ExtensionLoader as possible
final Map<String, List<String>> appModuleConfigFactories = getConfigSourceFactoryImpl(appModel.getAppArtifact());
if (!appModuleConfigFactories.isEmpty()) {
final Map<String, List<String>> allConfigFactories = new HashMap<>(appModuleConfigFactories.size());
final Map<String, byte[]> allowedConfigFactories = new HashMap<>(appModuleConfigFactories.size());
final Map<String, byte[]> bannedConfigFactories = new HashMap<>(appModuleConfigFactories.size());
for (Map.Entry<String, List<String>> appModuleFactories : appModuleConfigFactories.entrySet()) {
final String factoryImpl = appModuleFactories.getKey();
final Map<String, List<String>> unavailableConfigServices = getUnavailableConfigServices(appModel.getAppArtifact(),
deploymentClassLoader);
if (!unavailableConfigServices.isEmpty()) {
final Map<String, List<String>> allConfigServices = new HashMap<>(unavailableConfigServices.size());
final Map<String, byte[]> allowedConfigServices = new HashMap<>(unavailableConfigServices.size());
final Map<String, byte[]> bannedConfigServices = new HashMap<>(unavailableConfigServices.size());
for (Map.Entry<String, List<String>> appModuleServices : unavailableConfigServices.entrySet()) {
final String service = appModuleServices.getKey();
try {
ClassPathUtils.consumeAsPaths(deploymentClassLoader, factoryImpl, p -> {
ClassPathUtils.consumeAsPaths(deploymentClassLoader, service, p -> {
try {
allConfigFactories.computeIfAbsent(factoryImpl, k -> new ArrayList<>())
allConfigServices.computeIfAbsent(service, k -> new ArrayList<>())
.addAll(Files.readAllLines(p));
} catch (IOException e) {
throw new UncheckedIOException("Failed to read " + p, e);
Expand All @@ -198,25 +207,25 @@ public static Config getConfig(ApplicationModel appModel, LaunchMode launchMode,
} catch (IOException e) {
throw new CodeGenException("Failed to read resources from classpath", e);
}
final List<String> allFactories = allConfigFactories.getOrDefault(factoryImpl, List.of());
allFactories.removeAll(appModuleFactories.getValue());
if (allFactories.isEmpty()) {
bannedConfigFactories.put(factoryImpl, new byte[0]);
final List<String> allServices = allConfigServices.getOrDefault(service, List.of());
allServices.removeAll(appModuleServices.getValue());
if (allServices.isEmpty()) {
bannedConfigServices.put(service, new byte[0]);
} else {
final StringJoiner joiner = new StringJoiner(System.lineSeparator());
allFactories.forEach(joiner::add);
allowedConfigFactories.put(factoryImpl, joiner.toString().getBytes());
allServices.forEach(joiner::add);
allowedConfigServices.put(service, joiner.toString().getBytes());
}
}

// we don't want to load config source factories/providers from the current module because they haven't been compiled yet
// we don't want to load config services from the current module because they haven't been compiled yet
final QuarkusClassLoader.Builder configClBuilder = QuarkusClassLoader.builder("CodeGenerator Config ClassLoader",
deploymentClassLoader, false);
if (!allowedConfigFactories.isEmpty()) {
configClBuilder.addElement(new MemoryClassPathElement(allowedConfigFactories, true));
if (!allowedConfigServices.isEmpty()) {
configClBuilder.addElement(new MemoryClassPathElement(allowedConfigServices, true));
}
if (!bannedConfigFactories.isEmpty()) {
configClBuilder.addBannedElement(new MemoryClassPathElement(bannedConfigFactories, true));
if (!bannedConfigServices.isEmpty()) {
configClBuilder.addBannedElement(new MemoryClassPathElement(bannedConfigServices, true));
}
deploymentClassLoader = configClBuilder.build();
}
Expand All @@ -226,31 +235,51 @@ public static Config getConfig(ApplicationModel appModel, LaunchMode launchMode,
} catch (Exception e) {
throw new CodeGenException("Failed to initialize application configuration", e);
} finally {
if (!appModuleConfigFactories.isEmpty()) {
if (!unavailableConfigServices.isEmpty()) {
deploymentClassLoader.close();
}
}
}

private static Map<String, List<String>> getConfigSourceFactoryImpl(ResolvedDependency dep) throws CodeGenException {
final Map<String, List<String>> configFactoryImpl = new HashMap<>(CONFIG_SOURCE_FACTORY_INTERFACES.size());
private static Map<String, List<String>> getUnavailableConfigServices(ResolvedDependency dep, ClassLoader classLoader)
throws CodeGenException {
try (OpenPathTree openTree = dep.getContentTree().open()) {
for (String s : CONFIG_SOURCE_FACTORY_INTERFACES) {
openTree.accept(s, v -> {
if (v == null) {
return;
return openTree.apply(META_INF_SERVICES, visit -> {
if (visit == null) {
// the application module does not include META-INF/services entry
return Map.of();
}
Map<String, List<String>> unavailableServices = Map.of();
var servicesDir = visit.getPath();
for (String serviceClass : CONFIG_SERVICES) {
var serviceFile = servicesDir.resolve(serviceClass);
if (!Files.exists(serviceFile)) {
continue;
}
final List<String> implList;
try {
configFactoryImpl.put(s, Files.readAllLines(v.getPath()));
implList = Files.readAllLines(serviceFile);
} catch (IOException e) {
throw new UncheckedIOException("Failed to read " + v.getPath(), e);
throw new UncheckedIOException("Failed to read " + serviceFile, e);
}
});
}
final List<String> unavailableList = new ArrayList<>(implList.size());
for (String impl : implList) {
if (classLoader.getResource(impl.replace('.', '/') + ".class") == null) {
unavailableList.add(impl);
}
}
if (!unavailableList.isEmpty()) {
if (unavailableServices.isEmpty()) {
unavailableServices = new HashMap<>();
}
unavailableServices.put(META_INF_SERVICES + serviceClass, unavailableList);
}
}
return unavailableServices;
});
} catch (IOException e) {
throw new CodeGenException("Failed to read " + dep.getResolvedPaths(), e);
}
return configFactoryImpl;
}

private static Path codeGenOutDir(Path generatedSourcesDir,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ public static final class Version implements Comparable<Version> {
"(GraalVM|native-image)( Version)? " + VersionParseHelper.VERS_FORMAT + "(?<distro>.*?)?" +
"(\\(Java Version (?<jfeature>[0-9]+)(\\.(?<jinterim>[0-9]*)\\.(?<jupdate>[0-9]*))?.*)?$");

static final Version UNVERSIONED = new Version("Undefined", "snapshot", Distribution.ORACLE);
static final Version VERSION_21_3 = new Version("GraalVM 21.3", "21.3", Distribution.ORACLE);
static final Version VERSION_21_3_0 = new Version("GraalVM 21.3.0", "21.3.0", Distribution.ORACLE);
public static final Version VERSION_22_3_0 = new Version("GraalVM 22.3.0", "22.3.0", Distribution.ORACLE);
Expand Down Expand Up @@ -160,10 +159,6 @@ String getFullVersion() {
return fullVersion;
}

boolean isDetected() {
return this != UNVERSIONED;
}

boolean isObsolete() {
return this.compareTo(MINIMUM) < 0;
}
Expand Down Expand Up @@ -204,10 +199,7 @@ static Version of(Stream<String> output) {

if (lines.size() == 3) {
// Attempt to parse the new 3-line version scheme first.
Version v = VersionParseHelper.parse(lines);
if (v != VersionParseHelper.UNKNOWN_VERSION) {
return v;
}
return VersionParseHelper.parse(lines);
} else if (lines.size() == 1) {
// Old, single line version parsing logic
final String line = lines.get(0);
Expand All @@ -234,7 +226,8 @@ static Version of(Stream<String> output) {
}
}

return UNVERSIONED;
throw new IllegalArgumentException(
"Cannot parse version from output: " + output.collect(Collectors.joining("\n")));
}

private static boolean isMandrel(String s) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,7 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, LocalesBuildTimeCon

buildRunner.setup(processInheritIODisabled.isPresent() || processInheritIODisabledBuildItem.isPresent());
final GraalVM.Version graalVMVersion = buildRunner.getGraalVMVersion();

if (graalVMVersion.isDetected()) {
checkGraalVMVersion(graalVMVersion);
} else {
log.error("Unable to get GraalVM version from the native-image binary.");
}
checkGraalVMVersion(graalVMVersion);

try {
if (nativeConfig.cleanupServer()) {
Expand Down Expand Up @@ -568,7 +563,7 @@ static class Builder {
private Path outputDir;
private String runnerJarName;
private String noPIE = "";
private GraalVM.Version graalVMVersion = GraalVM.Version.UNVERSIONED;
private GraalVM.Version graalVMVersion = null;
private String nativeImageName;
private boolean classpathIsBroken;
private boolean containerBuild;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,19 +86,13 @@ public void testGraalVMVersionDetected() {
}

static void assertVersion(org.graalvm.home.Version graalVmVersion, Distribution distro, Version version) {
assertThat(version.isDetected()).isEqualTo(true);
assertThat(graalVmVersion.compareTo(version.version)).isEqualTo(0);
assertThat(version.distribution).isEqualTo(distro);
if (distro == MANDREL) {
assertThat(version.isMandrel()).isTrue();
}
}

@Test
public void testGraalVMVersionUndetected() {
assertThat(Version.of(Stream.of("foo bar")).isDetected()).isFalse();
}

@Test
public void testGraalVMVersionsOlderThan() {
assertOlderThan("GraalVM Version 19.3.6 CE", "GraalVM Version 20.2.0 (Java Version 11.0.9)");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,16 @@ protected void assertAppModel(ApplicationModel model) {
assertThat(d).isNotNull();
assertThat(d.isRuntimeCp()).isTrue();
assertThat(d.isDeploymentCp()).isTrue();
assertThat(d.isWorkspaceModule()).isFalse(); // limitation of the raw pom-based workspace discovery
assertThat(d.isReloadable()).isFalse();
assertThat(d.isWorkspaceModule()).isTrue();
assertThat(d.isReloadable()).isTrue();
assertThat(d.isRuntimeExtensionArtifact()).isFalse();

d = deps.get("common-library");
assertThat(d).isNotNull();
assertThat(d.isRuntimeCp()).isTrue();
assertThat(d.isDeploymentCp()).isTrue();
assertThat(d.isWorkspaceModule()).isTrue();
assertThat(d.isReloadable()).isFalse(); // since it's a dependency of a non-reloadable module
assertThat(d.isReloadable()).isTrue();
assertThat(d.isRuntimeExtensionArtifact()).isFalse();

d = deps.get("ext-a");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,24 +120,28 @@ private List<ConfigDocItem> recursivelyFindConfigItems(Element element, String r
throws JsonProcessingException {
List<ConfigDocItem> configDocItems = new ArrayList<>();
TypeElement asTypeElement = (TypeElement) element;
TypeMirror superType = asTypeElement.getSuperclass();
List<TypeMirror> superTypes = new ArrayList<>();
superTypes.add(asTypeElement.getSuperclass());
superTypes.addAll(asTypeElement.getInterfaces());

for (TypeMirror superType : superTypes) {
if (superType.getKind() != TypeKind.NONE && !superType.toString().equals(Object.class.getName())) {
String key = superType.toString();
String rawConfigItems = allConfigurationGroups.get(key);
if (rawConfigItems == null) {
rawConfigItems = allConfigurationRoots.get(key);
}
final List<ConfigDocItem> superTypeConfigItems;
if (rawConfigItems == null) { // element not yet scanned
Element superElement = ((DeclaredType) superType).asElement();
superTypeConfigItems = recursivelyFindConfigItems(superElement, rootName, parentName,
configPhase, withinAMap, sectionLevel, generateSeparateConfigGroupDocsFiles);
} else {
superTypeConfigItems = OBJECT_MAPPER.readValue(rawConfigItems, LIST_OF_CONFIG_ITEMS_TYPE_REF);
}

if (superType.getKind() != TypeKind.NONE && !superType.toString().equals(Object.class.getName())) {
String key = superType.toString();
String rawConfigItems = allConfigurationGroups.get(key);
if (rawConfigItems == null) {
rawConfigItems = allConfigurationRoots.get(key);
configDocItems.addAll(superTypeConfigItems);
}
final List<ConfigDocItem> superTypeConfigItems;
if (rawConfigItems == null) { // element not yet scanned
Element superElement = ((DeclaredType) superType).asElement();
superTypeConfigItems = recursivelyFindConfigItems(superElement, rootName, parentName,
configPhase, withinAMap, sectionLevel, generateSeparateConfigGroupDocsFiles);
} else {
superTypeConfigItems = OBJECT_MAPPER.readValue(rawConfigItems, LIST_OF_CONFIG_ITEMS_TYPE_REF);
}

configDocItems.addAll(superTypeConfigItems);
}

for (Element enclosedElement : element.getEnclosedElements()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package io.quarkus.runtime;

/**
* This is usually used for command mode applications with a startup logic. The logic is executed inside
* {@link QuarkusApplication#run} method before the main application exits.
*/
public interface QuarkusApplication {

int run(String... args) throws Exception;
Expand Down
Loading

0 comments on commit 9e6b6e8

Please sign in to comment.