diff --git a/extensions/hibernate-validator/deployment/src/main/java/io/quarkus/hibernate/validator/deployment/HibernateValidatorProcessor.java b/extensions/hibernate-validator/deployment/src/main/java/io/quarkus/hibernate/validator/deployment/HibernateValidatorProcessor.java index 7c8b6f1973c6c..981bcc2ca181c 100644 --- a/extensions/hibernate-validator/deployment/src/main/java/io/quarkus/hibernate/validator/deployment/HibernateValidatorProcessor.java +++ b/extensions/hibernate-validator/deployment/src/main/java/io/quarkus/hibernate/validator/deployment/HibernateValidatorProcessor.java @@ -54,7 +54,6 @@ import io.quarkus.arc.processor.BeanInfo; import io.quarkus.arc.processor.BuiltinScope; import io.quarkus.arc.processor.DotNames; -import io.quarkus.bootstrap.classloading.ClassPathElement; import io.quarkus.bootstrap.classloading.QuarkusClassLoader; import io.quarkus.deployment.Capabilities; import io.quarkus.deployment.Capability; @@ -364,11 +363,8 @@ void optionalResouceBundles(BuildProducer re AbstractMessageInterpolator.CONTRIBUTOR_VALIDATION_MESSAGES }; for (String potentialHibernateValidatorResourceBundle : potentialHibernateValidatorResourceBundles) { - for (ClassPathElement cpe : QuarkusClassLoader.getElements(potentialHibernateValidatorResourceBundle, false)) { - if (cpe.isRuntime()) { - resourceBundles.produce(new NativeImageResourceBundleBuildItem(potentialHibernateValidatorResourceBundle)); - break; - } + if (QuarkusClassLoader.isResourcePresentAtRuntime(potentialHibernateValidatorResourceBundle)) { + resourceBundles.produce(new NativeImageResourceBundleBuildItem(potentialHibernateValidatorResourceBundle)); } } } diff --git a/extensions/jackson/deployment/src/main/java/io/quarkus/jackson/deployment/JacksonProcessor.java b/extensions/jackson/deployment/src/main/java/io/quarkus/jackson/deployment/JacksonProcessor.java index 8c8f677d92561..6c7f88ff8fe5f 100755 --- a/extensions/jackson/deployment/src/main/java/io/quarkus/jackson/deployment/JacksonProcessor.java +++ b/extensions/jackson/deployment/src/main/java/io/quarkus/jackson/deployment/JacksonProcessor.java @@ -32,6 +32,7 @@ import io.quarkus.arc.deployment.GeneratedBeanBuildItem; import io.quarkus.arc.deployment.GeneratedBeanGizmoAdaptor; import io.quarkus.arc.deployment.UnremovableBeanBuildItem; +import io.quarkus.bootstrap.classloading.QuarkusClassLoader; import io.quarkus.deployment.Capabilities; import io.quarkus.deployment.Capability; import io.quarkus.deployment.annotations.BuildProducer; @@ -231,10 +232,8 @@ void autoRegisterModules(BuildProducer classPat private void registerModuleIfOnClassPath(String moduleClassName, BuildProducer classPathJacksonModules) { - try { - Class.forName(moduleClassName, false, Thread.currentThread().getContextClassLoader()); + if (QuarkusClassLoader.isClassPresentAtRuntime(moduleClassName)) { classPathJacksonModules.produce(new ClassPathJacksonModuleBuildItem(moduleClassName)); - } catch (Exception ignored) { } } diff --git a/extensions/kafka-client/deployment/src/main/java/io/quarkus/kafka/client/deployment/KafkaProcessor.java b/extensions/kafka-client/deployment/src/main/java/io/quarkus/kafka/client/deployment/KafkaProcessor.java index 6f508df693bc2..9a1e64dbf5d80 100644 --- a/extensions/kafka-client/deployment/src/main/java/io/quarkus/kafka/client/deployment/KafkaProcessor.java +++ b/extensions/kafka-client/deployment/src/main/java/io/quarkus/kafka/client/deployment/KafkaProcessor.java @@ -56,6 +56,7 @@ import io.quarkus.arc.deployment.AdditionalBeanBuildItem; import io.quarkus.arc.deployment.UnremovableBeanBuildItem; +import io.quarkus.bootstrap.classloading.QuarkusClassLoader; import io.quarkus.deployment.Capabilities; import io.quarkus.deployment.Capability; import io.quarkus.deployment.Feature; @@ -177,13 +178,11 @@ void relaxSaslElytron(BuildProducer config // If elytron is on the classpath and the Kafka connection uses SASL, the Elytron client SASL implementation // is stricter than what Kafka expects. In this case, configure the SASL client to relax some constraints. // See https://github.com/quarkusio/quarkus/issues/20088. - try { - Class.forName("org.wildfly.security.sasl.gssapi.AbstractGssapiMechanism", false, - Thread.currentThread().getContextClassLoader()); - config.produce(new RunTimeConfigurationDefaultBuildItem("kafka.wildfly.sasl.relax-compliance", "true")); - } catch (Exception e) { - // AbstractGssapiMechanism is not on the classpath, do not set wildfly.sasl.relax-compliance + if (!QuarkusClassLoader.isClassPresentAtRuntime("org.wildfly.security.sasl.gssapi.AbstractGssapiMechanism")) { + return; } + + config.produce(new RunTimeConfigurationDefaultBuildItem("kafka.wildfly.sasl.relax-compliance", "true")); } @BuildStep @@ -299,41 +298,35 @@ void checkBoostrapServers(KafkaRecorder recorder, Capabilities capabilities) { private void handleOpenTracing(BuildProducer reflectiveClass, Capabilities capabilities) { //opentracing contrib kafka interceptors: https://github.com/opentracing-contrib/java-kafka-client - if (capabilities.isPresent(Capability.OPENTRACING)) { - try { - Class.forName("io.opentracing.contrib.kafka.TracingProducerInterceptor", false, - Thread.currentThread().getContextClassLoader()); - reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, false, - "io.opentracing.contrib.kafka.TracingProducerInterceptor", - "io.opentracing.contrib.kafka.TracingConsumerInterceptor")); - } catch (ClassNotFoundException e) { - //ignore, opentracing contrib kafka is not in the classpath - } + if (!capabilities.isPresent(Capability.OPENTRACING) + || !QuarkusClassLoader.isClassPresentAtRuntime("io.opentracing.contrib.kafka.TracingProducerInterceptor")) { + return; } + + reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, false, + "io.opentracing.contrib.kafka.TracingProducerInterceptor", + "io.opentracing.contrib.kafka.TracingConsumerInterceptor")); } private void handleStrimziOAuth(BuildProducer reflectiveClass) { - try { - Class.forName("io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler", false, - Thread.currentThread().getContextClassLoader()); - - reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, true, - "io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler")); - - reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, true, - "org.keycloak.jose.jws.JWSHeader", - "org.keycloak.representations.AccessToken", - "org.keycloak.representations.AccessToken$Access", - "org.keycloak.representations.AccessTokenResponse", - "org.keycloak.representations.IDToken", - "org.keycloak.representations.JsonWebToken", - "org.keycloak.jose.jwk.JSONWebKeySet", - "org.keycloak.jose.jwk.JWK", - "org.keycloak.json.StringOrArrayDeserializer", - "org.keycloak.json.StringListMapDeserializer")); - } catch (ClassNotFoundException e) { - //ignore, Strimzi OAuth Client is not on the classpath + if (!QuarkusClassLoader.isClassPresentAtRuntime("io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler")) { + return; } + + reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, true, + "io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler")); + + reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, true, + "org.keycloak.jose.jws.JWSHeader", + "org.keycloak.representations.AccessToken", + "org.keycloak.representations.AccessToken$Access", + "org.keycloak.representations.AccessTokenResponse", + "org.keycloak.representations.IDToken", + "org.keycloak.representations.JsonWebToken", + "org.keycloak.jose.jwk.JSONWebKeySet", + "org.keycloak.jose.jwk.JWK", + "org.keycloak.json.StringOrArrayDeserializer", + "org.keycloak.json.StringListMapDeserializer")); } private void handleAvro(BuildProducer reflectiveClass, @@ -344,9 +337,7 @@ private void handleAvro(BuildProducer reflectiveClass, // Avro - for both Confluent and Apicurio // --- Confluent --- - try { - Class.forName("io.confluent.kafka.serializers.KafkaAvroDeserializer", false, - Thread.currentThread().getContextClassLoader()); + if (QuarkusClassLoader.isClassPresentAtRuntime("io.confluent.kafka.serializers.KafkaAvroDeserializer")) { reflectiveClass .produce(new ReflectiveClassBuildItem(true, false, "io.confluent.kafka.serializers.KafkaAvroDeserializer", @@ -381,27 +372,20 @@ private void handleAvro(BuildProducer reflectiveClass, "io.confluent.kafka.schemaregistry.client.rest.entities.requests.ModeUpdateRequest", "io.confluent.kafka.schemaregistry.client.rest.entities.requests.RegisterSchemaRequest", "io.confluent.kafka.schemaregistry.client.rest.entities.requests.RegisterSchemaResponse")); - } catch (ClassNotFoundException e) { - //ignore, Confluent Avro is not in the classpath } - try { - Class.forName("io.confluent.kafka.schemaregistry.client.security.basicauth.BasicAuthCredentialProvider", false, - Thread.currentThread().getContextClassLoader()); + if (QuarkusClassLoader.isClassPresentAtRuntime( + "io.confluent.kafka.schemaregistry.client.security.basicauth.BasicAuthCredentialProvider")) { serviceProviders .produce(new ServiceProviderBuildItem( "io.confluent.kafka.schemaregistry.client.security.basicauth.BasicAuthCredentialProvider", "io.confluent.kafka.schemaregistry.client.security.basicauth.SaslBasicAuthCredentialProvider", "io.confluent.kafka.schemaregistry.client.security.basicauth.UrlBasicAuthCredentialProvider", "io.confluent.kafka.schemaregistry.client.security.basicauth.UserInfoCredentialProvider")); - } catch (ClassNotFoundException e) { - // ignore, Confluent schema registry client not in the classpath } // --- Apicurio Registry 1.x --- - try { - Class.forName("io.apicurio.registry.utils.serde.AvroKafkaDeserializer", false, - Thread.currentThread().getContextClassLoader()); + if (QuarkusClassLoader.isClassPresentAtRuntime("io.apicurio.registry.utils.serde.AvroKafkaDeserializer")) { reflectiveClass.produce( new ReflectiveClassBuildItem(true, true, false, "io.apicurio.registry.utils.serde.AvroKafkaDeserializer", @@ -423,22 +407,13 @@ private void handleAvro(BuildProducer reflectiveClass, // Apicurio uses dynamic proxies, register them proxies.produce(new NativeImageProxyDefinitionBuildItem("io.apicurio.registry.client.RegistryService", "java.lang.AutoCloseable")); - - } catch (ClassNotFoundException e) { - // ignore, Apicurio Avro is not in the classpath } // --- Apicurio Registry 2.x --- - try { - Class.forName("io.apicurio.registry.serde.avro.AvroKafkaDeserializer", false, - Thread.currentThread().getContextClassLoader()); - - if (!capabilities.isPresent(Capability.APICURIO_REGISTRY_AVRO)) { - throw new RuntimeException( - "Apicurio Registry 2.x Avro classes detected, please use the quarkus-apicurio-registry-avro extension"); - } - } catch (ClassNotFoundException e) { - // ignore, Apicurio Avro is not in the classpath + if (QuarkusClassLoader.isClassPresentAtRuntime("io.apicurio.registry.serde.avro.AvroKafkaDeserializer") + && !capabilities.isPresent(Capability.APICURIO_REGISTRY_AVRO)) { + throw new RuntimeException( + "Apicurio Registry 2.x Avro classes detected, please use the quarkus-apicurio-registry-avro extension"); } } diff --git a/extensions/kotlin/deployment/src/main/java/io/quarkus/kotlin/deployment/KotlinProcessor.java b/extensions/kotlin/deployment/src/main/java/io/quarkus/kotlin/deployment/KotlinProcessor.java index 61cd0e1ece20a..e031aaa262d1c 100644 --- a/extensions/kotlin/deployment/src/main/java/io/quarkus/kotlin/deployment/KotlinProcessor.java +++ b/extensions/kotlin/deployment/src/main/java/io/quarkus/kotlin/deployment/KotlinProcessor.java @@ -2,6 +2,7 @@ import static io.quarkus.deployment.builditem.nativeimage.NativeImageResourcePatternsBuildItem.builder; +import io.quarkus.bootstrap.classloading.QuarkusClassLoader; import io.quarkus.deployment.Feature; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; @@ -27,11 +28,11 @@ FeatureBuildItem feature() { */ @BuildStep void registerKotlinJacksonModule(BuildProducer classPathJacksonModules) { - try { - Class.forName(KOTLIN_JACKSON_MODULE, false, Thread.currentThread().getContextClassLoader()); - classPathJacksonModules.produce(new ClassPathJacksonModuleBuildItem(KOTLIN_JACKSON_MODULE)); - } catch (Exception ignored) { + if (!QuarkusClassLoader.isClassPresentAtRuntime(KOTLIN_JACKSON_MODULE)) { + return; } + + classPathJacksonModules.produce(new ClassPathJacksonModuleBuildItem(KOTLIN_JACKSON_MODULE)); } /** diff --git a/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java b/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java index ad04bbcd96b9a..a0346428a2c39 100644 --- a/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java +++ b/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java @@ -17,6 +17,7 @@ import io.netty.util.internal.logging.InternalLoggerFactory; import io.quarkus.arc.deployment.AdditionalBeanBuildItem; import io.quarkus.arc.deployment.SyntheticBeanBuildItem; +import io.quarkus.bootstrap.classloading.QuarkusClassLoader; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.annotations.ExecutionTime; @@ -107,59 +108,49 @@ NativeImageConfigBuildItem build( .addRuntimeInitializedClass("io.netty.buffer.ByteBufUtil") .addNativeImageSystemProperty("io.netty.leakDetection.level", "DISABLED"); - try { - Class.forName("io.netty.handler.codec.http.HttpObjectEncoder"); + if (QuarkusClassLoader.isClassPresentAtRuntime("io.netty.handler.codec.http.HttpObjectEncoder")) { builder .addRuntimeInitializedClass("io.netty.handler.codec.http.HttpObjectEncoder") .addRuntimeInitializedClass("io.netty.handler.codec.http.websocketx.extensions.compression.DeflateDecoder") .addRuntimeInitializedClass("io.netty.handler.codec.http.websocketx.WebSocket00FrameEncoder"); - } catch (ClassNotFoundException e) { - //ignore + } else { log.debug("Not registering Netty HTTP classes as they were not found"); } - try { - Class.forName("io.netty.handler.codec.http2.Http2CodecUtil"); + if (QuarkusClassLoader.isClassPresentAtRuntime("io.netty.handler.codec.http2.Http2CodecUtil")) { builder .addRuntimeInitializedClass("io.netty.handler.codec.http2.Http2CodecUtil") .addRuntimeInitializedClass("io.netty.handler.codec.http2.Http2ClientUpgradeCodec") .addRuntimeInitializedClass("io.netty.handler.codec.http2.DefaultHttp2FrameWriter") .addRuntimeInitializedClass("io.netty.handler.codec.http2.Http2ConnectionHandler"); - } catch (ClassNotFoundException e) { - //ignore + } else { log.debug("Not registering Netty HTTP2 classes as they were not found"); } - try { - Class.forName("io.netty.channel.unix.UnixChannel"); + if (QuarkusClassLoader.isClassPresentAtRuntime("io.netty.channel.unix.UnixChannel")) { builder.addRuntimeInitializedClass("io.netty.channel.unix.Errors") .addRuntimeInitializedClass("io.netty.channel.unix.FileDescriptor") .addRuntimeInitializedClass("io.netty.channel.unix.IovArray") .addRuntimeInitializedClass("io.netty.channel.unix.Limits"); - } catch (ClassNotFoundException e) { - //ignore + } else { log.debug("Not registering Netty native unix classes as they were not found"); } - try { - Class.forName("io.netty.channel.epoll.EpollMode"); + if (QuarkusClassLoader.isClassPresentAtRuntime("io.netty.channel.epoll.EpollMode")) { builder.addRuntimeInitializedClass("io.netty.channel.epoll.Epoll") .addRuntimeInitializedClass("io.netty.channel.epoll.EpollEventArray") .addRuntimeInitializedClass("io.netty.channel.epoll.EpollEventLoop") .addRuntimeInitializedClass("io.netty.channel.epoll.Native"); - } catch (ClassNotFoundException e) { - //ignore + } else { log.debug("Not registering Netty native epoll classes as they were not found"); } - try { - Class.forName("io.netty.channel.kqueue.AcceptFilter"); + if (QuarkusClassLoader.isClassPresentAtRuntime("io.netty.channel.kqueue.AcceptFilter")) { builder.addRuntimeInitializedClass("io.netty.channel.kqueue.KQueue") .addRuntimeInitializedClass("io.netty.channel.kqueue.KQueueEventArray") .addRuntimeInitializedClass("io.netty.channel.kqueue.KQueueEventLoop") .addRuntimeInitializedClass("io.netty.channel.kqueue.Native"); - } catch (ClassNotFoundException e) { - //ignore + } else { log.debug("Not registering Netty native kqueue classes as they were not found"); } diff --git a/extensions/opentelemetry/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/OpenTelemetryProcessor.java b/extensions/opentelemetry/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/OpenTelemetryProcessor.java index 5d6bac8fc451d..8374f7bf61a1f 100644 --- a/extensions/opentelemetry/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/OpenTelemetryProcessor.java +++ b/extensions/opentelemetry/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/OpenTelemetryProcessor.java @@ -14,6 +14,7 @@ import io.quarkus.arc.deployment.AnnotationsTransformerBuildItem; import io.quarkus.arc.deployment.InterceptorBindingRegistrarBuildItem; import io.quarkus.arc.processor.InterceptorBindingRegistrar; +import io.quarkus.bootstrap.classloading.QuarkusClassLoader; import io.quarkus.deployment.Feature; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; @@ -130,11 +131,6 @@ void storeVertxOnContextStorage(OpenTelemetryRecorder recorder, CoreVertxBuildIt } public static boolean isClassPresent(String classname) { - try { - Class.forName(classname, false, Thread.currentThread().getContextClassLoader()); - return true; - } catch (ClassNotFoundException e) { - return false; - } + return QuarkusClassLoader.isClassPresentAtRuntime(classname); } } diff --git a/extensions/resteasy-classic/resteasy-server-common/deployment/src/main/java/io/quarkus/resteasy/server/common/deployment/ResteasyServerCommonProcessor.java b/extensions/resteasy-classic/resteasy-server-common/deployment/src/main/java/io/quarkus/resteasy/server/common/deployment/ResteasyServerCommonProcessor.java index 96da8f5c108fa..fe3f2df8ce4ad 100755 --- a/extensions/resteasy-classic/resteasy-server-common/deployment/src/main/java/io/quarkus/resteasy/server/common/deployment/ResteasyServerCommonProcessor.java +++ b/extensions/resteasy-classic/resteasy-server-common/deployment/src/main/java/io/quarkus/resteasy/server/common/deployment/ResteasyServerCommonProcessor.java @@ -56,7 +56,6 @@ import io.quarkus.arc.processor.BuiltinScope; import io.quarkus.arc.processor.DotNames; import io.quarkus.arc.processor.Transformation; -import io.quarkus.bootstrap.classloading.ClassPathElement; import io.quarkus.bootstrap.classloading.QuarkusClassLoader; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; @@ -184,10 +183,8 @@ static final class ResteasyConfig { @BuildStep NativeImageResourceBundleBuildItem optionalResourceBundle() { - for (ClassPathElement cpe : QuarkusClassLoader.getElements(MESSAGES_RESOURCE_BUNDLE, false)) { - if (cpe.isRuntime()) { - return new NativeImageResourceBundleBuildItem(MESSAGES_RESOURCE_BUNDLE); - } + if (QuarkusClassLoader.isResourcePresentAtRuntime(MESSAGES_RESOURCE_BUNDLE)) { + return new NativeImageResourceBundleBuildItem(MESSAGES_RESOURCE_BUNDLE); } return null; diff --git a/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java b/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java index b037afb10decc..d8b2ecc6c4b9d 100644 --- a/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java +++ b/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java @@ -116,6 +116,7 @@ import io.quarkus.arc.processor.DotNames; import io.quarkus.arc.processor.MethodDescriptors; import io.quarkus.arc.processor.Types; +import io.quarkus.bootstrap.classloading.QuarkusClassLoader; import io.quarkus.deployment.Capabilities; import io.quarkus.deployment.Capability; import io.quarkus.deployment.GeneratedClassGizmoAdaptor; @@ -1853,9 +1854,7 @@ private void handleReturn(ClassInfo restClientInterface, String defaultMediaType continuationIndex = parameters.size() - 1; returnCategory = ReturnCategory.COROUTINE; - try { - Thread.currentThread().getContextClassLoader().loadClass(UNI_KT.toString()); - } catch (ClassNotFoundException e) { + if (!QuarkusClassLoader.isClassPresentAtRuntime(UNI_KT.toString())) { //TODO: make this automatic somehow throw new RuntimeException("Suspendable rest client method" + jandexMethod + " is present on class " + jandexMethod.declaringClass() diff --git a/extensions/scala/deployment/src/main/java/io/quarkus/scala/deployment/ScalaProcessor.java b/extensions/scala/deployment/src/main/java/io/quarkus/scala/deployment/ScalaProcessor.java index bfa4f0d823d77..56a191677b81f 100644 --- a/extensions/scala/deployment/src/main/java/io/quarkus/scala/deployment/ScalaProcessor.java +++ b/extensions/scala/deployment/src/main/java/io/quarkus/scala/deployment/ScalaProcessor.java @@ -1,5 +1,6 @@ package io.quarkus.scala.deployment; +import io.quarkus.bootstrap.classloading.QuarkusClassLoader; import io.quarkus.deployment.Feature; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; @@ -22,10 +23,10 @@ FeatureBuildItem feature() { */ @BuildStep void registerScalaJacksonModule(BuildProducer classPathJacksonModules) { - try { - Class.forName(SCALA_JACKSON_MODULE, false, Thread.currentThread().getContextClassLoader()); - classPathJacksonModules.produce(new ClassPathJacksonModuleBuildItem(SCALA_JACKSON_MODULE)); - } catch (Exception ignored) { + if (!QuarkusClassLoader.isClassPresentAtRuntime(SCALA_JACKSON_MODULE)) { + return; } + + classPathJacksonModules.produce(new ClassPathJacksonModuleBuildItem(SCALA_JACKSON_MODULE)); } } diff --git a/extensions/scheduler/deployment/src/main/java/io/quarkus/scheduler/deployment/SchedulerProcessor.java b/extensions/scheduler/deployment/src/main/java/io/quarkus/scheduler/deployment/SchedulerProcessor.java index 96ce287992775..ed590c058e17f 100644 --- a/extensions/scheduler/deployment/src/main/java/io/quarkus/scheduler/deployment/SchedulerProcessor.java +++ b/extensions/scheduler/deployment/src/main/java/io/quarkus/scheduler/deployment/SchedulerProcessor.java @@ -52,6 +52,7 @@ import io.quarkus.arc.processor.BuiltinScope; import io.quarkus.arc.processor.DotNames; import io.quarkus.arc.runtime.BeanLookupSupplier; +import io.quarkus.bootstrap.classloading.QuarkusClassLoader; import io.quarkus.deployment.Capabilities; import io.quarkus.deployment.Capability; import io.quarkus.deployment.Feature; @@ -601,15 +602,13 @@ UnremovableBeanBuildItem unremoveableSkipPredicates() { @BuildStep void produceCoroutineScope(BuildProducer buildItemBuildProducer) { - try { - Thread.currentThread().getContextClassLoader().loadClass("kotlinx.coroutines.CoroutineScope"); - buildItemBuildProducer.produce(AdditionalBeanBuildItem.builder() - .addBeanClass("io.quarkus.scheduler.kotlin.runtime.ApplicationCoroutineScope") - .setUnremovable().build()); - } catch (ClassNotFoundException e) { - // ignore + if (!QuarkusClassLoader.isClassPresentAtRuntime("kotlinx.coroutines.CoroutineScope")) { + return; } + buildItemBuildProducer.produce(AdditionalBeanBuildItem.builder() + .addBeanClass("io.quarkus.scheduler.kotlin.runtime.ApplicationCoroutineScope") + .setUnremovable().build()); } } diff --git a/extensions/smallrye-reactive-messaging/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/deployment/SmallRyeReactiveMessagingProcessor.java b/extensions/smallrye-reactive-messaging/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/deployment/SmallRyeReactiveMessagingProcessor.java index d1fbfe7407b22..b9ca570ca90e5 100644 --- a/extensions/smallrye-reactive-messaging/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/deployment/SmallRyeReactiveMessagingProcessor.java +++ b/extensions/smallrye-reactive-messaging/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/deployment/SmallRyeReactiveMessagingProcessor.java @@ -37,6 +37,7 @@ import io.quarkus.arc.processor.AnnotationsTransformer; import io.quarkus.arc.processor.BeanInfo; import io.quarkus.arc.processor.DotNames; +import io.quarkus.bootstrap.classloading.QuarkusClassLoader; import io.quarkus.builder.item.SimpleBuildItem; import io.quarkus.deployment.Feature; import io.quarkus.deployment.GeneratedClassGizmoAdaptor; @@ -448,10 +449,9 @@ private boolean doesImplement(ClassInfo clazz, DotName iface, IndexView index) { @BuildStep CoroutineConfigurationBuildItem producesCoroutineConfiguration() { - try { - Class.forName("kotlinx.coroutines.future.FutureKt", false, getClass().getClassLoader()); + if (QuarkusClassLoader.isClassPresentAtRuntime("kotlinx.coroutines.future.FutureKt")) { return new CoroutineConfigurationBuildItem(true); - } catch (ClassNotFoundException e) { + } else { return new CoroutineConfigurationBuildItem(false); } } diff --git a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java index 55961a70b3f70..74fb4c0009f6a 100644 --- a/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java +++ b/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java @@ -47,6 +47,33 @@ public static List getElements(String resourceName, boolean lo return ((QuarkusClassLoader) ccl).getElementsWithResource(resourceName, localOnly); } + /** + * Indicates if a given class is present at runtime. + * + * @param resourceName the path of the resource, for instance {@code path/to/my-resources.properties} for a properties file + * or {@code my/package/MyClass.class} for a class. + */ + public static boolean isClassPresentAtRuntime(String className) { + return isResourcePresentAtRuntime(className.replace('.', '/') + ".class"); + } + + /** + * Indicates if a given resource is present at runtime. + * Can also be used to check if a class is present as a class is just a regular resource. + * + * @param resourceName the path of the resource, for instance {@code path/to/my-resources.properties} for a properties file + * or {@code my/package/MyClass.class} for a class. + */ + public static boolean isResourcePresentAtRuntime(String resourcePath) { + for (ClassPathElement cpe : QuarkusClassLoader.getElements(resourcePath, false)) { + if (cpe.isRuntime()) { + return true; + } + } + + return false; + } + private final String name; private final List elements; private final ConcurrentMap protectionDomains = new ConcurrentHashMap<>();