This is an automated email from the ASF dual-hosted git repository. ppalaga pushed a commit to branch camel-master in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/camel-master by this push: new c46d142 Fix #1664 KuduIT fails with Camel 3.5.0 c46d142 is described below commit c46d14230b08283c002b7d5fd97a2daf8d83b341 Author: Peter Palaga <ppal...@redhat.com> AuthorDate: Tue Sep 1 13:42:15 2020 +0200 Fix #1664 KuduIT fails with Camel 3.5.0 --- .../kudu/deployment/JBossNettyLoggerFactory.java | 197 +++++++++ .../component/kudu/deployment/KuduProcessor.java | 169 ++++++++ extensions/kudu/runtime/pom.xml | 5 + .../component/kudu/graal/EmptyByteBufStub.java | 53 +++ .../component/kudu/graal/NettySubstitutions.java | 453 +++++++++++++++++++++ .../component/kudu/graal/ZLibSubstitutions.java | 88 ++++ 6 files changed, 965 insertions(+) diff --git a/extensions/kudu/deployment/src/main/java/org/apache/camel/quarkus/component/kudu/deployment/JBossNettyLoggerFactory.java b/extensions/kudu/deployment/src/main/java/org/apache/camel/quarkus/component/kudu/deployment/JBossNettyLoggerFactory.java new file mode 100644 index 0000000..0e2520b --- /dev/null +++ b/extensions/kudu/deployment/src/main/java/org/apache/camel/quarkus/component/kudu/deployment/JBossNettyLoggerFactory.java @@ -0,0 +1,197 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.kudu.deployment; + +import org.apache.kudu.shaded.io.netty.util.internal.logging.AbstractInternalLogger; +import org.apache.kudu.shaded.io.netty.util.internal.logging.InternalLogger; +import org.apache.kudu.shaded.io.netty.util.internal.logging.InternalLoggerFactory; +import org.jboss.logging.Logger; + +/** + * Adapted from + * https://github.com/quarkusio/quarkus/blob/master/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/JBossNettyLoggerFactory.java + * + */ +public class JBossNettyLoggerFactory extends InternalLoggerFactory { + + @Override + protected InternalLogger newInstance(String name) { + return new JBossNettyInternalLogger(name); + } + + private static final class JBossNettyInternalLogger extends AbstractInternalLogger { + + final Logger log; + + JBossNettyInternalLogger(String name) { + super(name); + log = Logger.getLogger(name); + } + + @Override + public boolean isTraceEnabled() { + return log.isTraceEnabled(); + } + + @Override + public void trace(String msg) { + log.trace(msg); + } + + @Override + public void trace(String format, Object arg) { + log.tracef(format, arg); + } + + @Override + public void trace(String format, Object argA, Object argB) { + log.tracef(format, argA, argB); + } + + @Override + public void trace(String format, Object... arguments) { + log.tracef(format, arguments); + } + + @Override + public void trace(String msg, Throwable t) { + log.trace(msg, t); + } + + @Override + public boolean isDebugEnabled() { + return log.isDebugEnabled(); + } + + @Override + public void debug(String msg) { + log.debug(msg); + } + + @Override + public void debug(String format, Object arg) { + log.debugf(format, arg); + } + + @Override + public void debug(String format, Object argA, Object argB) { + log.debugf(format, argA, argB); + } + + @Override + public void debug(String format, Object... arguments) { + log.debugf(format, arguments); + } + + @Override + public void debug(String msg, Throwable t) { + log.debug(msg, t); + } + + @Override + public boolean isInfoEnabled() { + return log.isInfoEnabled(); + } + + @Override + public void info(String msg) { + log.info(msg); + } + + @Override + public void info(String format, Object arg) { + log.infof(format, arg); + } + + @Override + public void info(String format, Object argA, Object argB) { + log.infof(format, argA, argB); + } + + @Override + public void info(String format, Object... arguments) { + log.infof(format, arguments); + } + + @Override + public void info(String msg, Throwable t) { + log.info(msg, t); + } + + @Override + public boolean isWarnEnabled() { + return log.isEnabled(Logger.Level.WARN); + } + + @Override + public void warn(String msg) { + log.warn(msg); + } + + @Override + public void warn(String format, Object arg) { + log.warnf(format, arg); + } + + @Override + public void warn(String format, Object... arguments) { + log.warnf(format, arguments); + } + + @Override + public void warn(String format, Object argA, Object argB) { + log.warnf(format, argA, argB); + } + + @Override + public void warn(String msg, Throwable t) { + log.warn(msg, t); + } + + @Override + public boolean isErrorEnabled() { + return log.isEnabled(Logger.Level.ERROR); + } + + @Override + public void error(String msg) { + log.error(msg); + } + + @Override + public void error(String format, Object arg) { + log.errorf(format, arg); + } + + @Override + public void error(String format, Object argA, Object argB) { + log.errorf(format, argA, argB); + } + + @Override + public void error(String format, Object... arguments) { + log.errorf(format, arguments); + } + + @Override + public void error(String msg, Throwable t) { + log.error(msg, t); + } + + } + +} diff --git a/extensions/kudu/deployment/src/main/java/org/apache/camel/quarkus/component/kudu/deployment/KuduProcessor.java b/extensions/kudu/deployment/src/main/java/org/apache/camel/quarkus/component/kudu/deployment/KuduProcessor.java index d130641..56dee82 100644 --- a/extensions/kudu/deployment/src/main/java/org/apache/camel/quarkus/component/kudu/deployment/KuduProcessor.java +++ b/extensions/kudu/deployment/src/main/java/org/apache/camel/quarkus/component/kudu/deployment/KuduProcessor.java @@ -16,11 +16,27 @@ */ package org.apache.camel.quarkus.component.kudu.deployment; +import java.util.Arrays; +import java.util.List; + +import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem; import io.quarkus.deployment.builditem.FeatureBuildItem; +import io.quarkus.deployment.builditem.nativeimage.NativeImageConfigBuildItem; +import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; +import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem; +import io.quarkus.deployment.builditem.nativeimage.RuntimeReinitializedClassBuildItem; +import io.quarkus.deployment.builditem.nativeimage.UnsafeAccessedFieldBuildItem; +import org.apache.camel.quarkus.component.kudu.graal.EmptyByteBufStub; +import org.apache.kudu.shaded.io.netty.util.internal.logging.InternalLoggerFactory; +import org.jboss.logging.Logger; class KuduProcessor { + private static final Logger LOGGER = Logger.getLogger(KuduProcessor.class); + static { + InternalLoggerFactory.setDefaultFactory(new JBossNettyLoggerFactory()); + } private static final String FEATURE = "camel-kudu"; @@ -34,4 +50,157 @@ class KuduProcessor { return new ExtensionSslNativeSupportBuildItem(FEATURE); } + @BuildStep + void reflection(BuildProducer<ReflectiveClassBuildItem> reflectiveClass) { + reflectiveClass.produce(new ReflectiveClassBuildItem(true, false, + "org.apache.kudu.tserver.Tserver$ResourceMetricsPB", + "org.apache.kudu.tserver.Tserver$ResourceMetricsPB$Builder")); + } + + /* + * Adapted from https://github.com/quarkusio/quarkus/blob/master/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java + */ + @BuildStep + void netty( + BuildProducer<NativeImageConfigBuildItem> nativeImageConfig, + BuildProducer<ReflectiveClassBuildItem> reflectiveClass) { + + reflectiveClass.produce(new ReflectiveClassBuildItem(true, false, + "org.apache.kudu.tserver.Tserver$ResourceMetricsPB", + "org.apache.kudu.tserver.Tserver$ResourceMetricsPB$Builder")); + + reflectiveClass.produce(new ReflectiveClassBuildItem(false, false, + "org.apache.kudu.shaded.io.netty.channel.socket.nio.NioSocketChannel")); + reflectiveClass + .produce(new ReflectiveClassBuildItem(false, false, + "org.apache.kudu.shaded.io.netty.channel.socket.nio.NioServerSocketChannel")); + reflectiveClass.produce(new ReflectiveClassBuildItem(false, false, "java.util.LinkedHashMap")); + reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, "sun.nio.ch.SelectorImpl")); + + NativeImageConfigBuildItem.Builder builder = NativeImageConfigBuildItem.builder() + //.addNativeImageSystemProperty("io.netty.noUnsafe", "true") + // Use small chunks to avoid a lot of wasted space. Default is 16mb * arenas (derived from core count) + // Since buffers are cached to threads, the malloc overhead is temporary anyway + .addNativeImageSystemProperty("io.netty.allocator.maxOrder", "1") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.ssl.JdkNpnApplicationProtocolNegotiator") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.ssl.ConscryptAlpnSslEngine") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.ssl.ReferenceCountedOpenSslEngine") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.ssl.ReferenceCountedOpenSslContext") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.ssl.ReferenceCountedOpenSslClientContext") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.ssl.util.ThreadLocalInsecureRandom") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.buffer.ByteBufUtil$HexUtil") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.buffer.PooledByteBufAllocator") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.buffer.ByteBufAllocator") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.buffer.ByteBufUtil") + .addNativeImageSystemProperty("io.netty.leakDetection.level", "DISABLED"); + + try { + Class.forName("org.apache.kudu.shaded.io.netty.handler.codec.http.HttpObjectEncoder"); + builder + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.codec.http.HttpObjectEncoder") + .addRuntimeInitializedClass( + "org.apache.kudu.shaded.io.netty.handler.codec.http.websocketx.extensions.compression.DeflateDecoder") + .addRuntimeInitializedClass( + "org.apache.kudu.shaded.io.netty.handler.codec.http.websocketx.WebSocket00FrameEncoder"); + } catch (ClassNotFoundException e) { + //ignore + LOGGER.debug("Not registering Netty HTTP classes as they were not found"); + } + + try { + Class.forName("org.apache.kudu.shaded.io.netty.handler.codec.http2.Http2CodecUtil"); + builder + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.codec.http2.Http2CodecUtil") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.codec.http2.Http2ClientUpgradeCodec") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.codec.http2.DefaultHttp2FrameWriter") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler"); + } catch (ClassNotFoundException e) { + //ignore + LOGGER.debug("Not registering Netty HTTP2 classes as they were not found"); + } + + try { + Class.forName("org.apache.kudu.shaded.io.netty.channel.unix.UnixChannel"); + builder.addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.unix.Errors") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.unix.FileDescriptor") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.unix.IovArray") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.unix.Limits"); + } catch (ClassNotFoundException e) { + //ignore + LOGGER.debug("Not registering Netty native unix classes as they were not found"); + } + + try { + Class.forName("org.apache.kudu.shaded.io.netty.channel.epoll.EpollMode"); + builder.addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.epoll.Epoll") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.epoll.EpollEventArray") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.epoll.EpollEventLoop") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.epoll.Native"); + } catch (ClassNotFoundException e) { + //ignore + LOGGER.debug("Not registering Netty native epoll classes as they were not found"); + } + + try { + Class.forName("org.apache.kudu.shaded.io.netty.channel.kqueue.AcceptFilter"); + builder.addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.kqueue.KQueue") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.kqueue.KQueueEventArray") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.kqueue.KQueueEventLoop") + .addRuntimeInitializedClass("org.apache.kudu.shaded.io.netty.channel.kqueue.Native"); + } catch (ClassNotFoundException e) { + //ignore + LOGGER.debug("Not registering Netty native kqueue classes as they were not found"); + } + + nativeImageConfig.produce(builder.build()); + } + + /* + * Adapted from https://github.com/quarkusio/quarkus/blob/master/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java + */ + @BuildStep + public RuntimeReinitializedClassBuildItem nettyReinitScheduledFutureTask() { + return new RuntimeReinitializedClassBuildItem( + "org.apache.camel.quarkus.component.kudu.graal.Holder_io_netty_util_concurrent_ScheduledFutureTask"); + } + + /* + * Adapted from https://github.com/quarkusio/quarkus/blob/master/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java + */ + @BuildStep + public List<UnsafeAccessedFieldBuildItem> nettyUnsafeAccessedFields() { + return Arrays.asList( + new UnsafeAccessedFieldBuildItem("sun.nio.ch.SelectorImpl", "selectedKeys"), + new UnsafeAccessedFieldBuildItem("sun.nio.ch.SelectorImpl", "publicSelectedKeys"), + + new UnsafeAccessedFieldBuildItem( + "org.apache.kudu.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField", + "producerIndex"), + new UnsafeAccessedFieldBuildItem( + "org.apache.kudu.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField", + "producerLimit"), + new UnsafeAccessedFieldBuildItem( + "org.apache.kudu.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField", + "consumerIndex"), + + new UnsafeAccessedFieldBuildItem( + "org.apache.kudu.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields", + "producerIndex"), + new UnsafeAccessedFieldBuildItem( + "org.apache.kudu.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields", + "producerLimit"), + new UnsafeAccessedFieldBuildItem( + "org.apache.kudu.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields", + "consumerIndex")); + } + + /* + * Adapted from https://github.com/quarkusio/quarkus/blob/master/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java + */ + @BuildStep + RuntimeInitializedClassBuildItem nettyRuntimeInitBcryptUtil() { + // this holds a direct allocated byte buffer that needs to be initialised at run time + return new RuntimeInitializedClassBuildItem(EmptyByteBufStub.class.getName()); + } + } diff --git a/extensions/kudu/runtime/pom.xml b/extensions/kudu/runtime/pom.xml index ee37afd..11403aa 100644 --- a/extensions/kudu/runtime/pom.xml +++ b/extensions/kudu/runtime/pom.xml @@ -54,6 +54,11 @@ <groupId>org.apache.camel</groupId> <artifactId>camel-kudu</artifactId> </dependency> + <dependency> + <groupId>org.graalvm.nativeimage</groupId> + <artifactId>svm</artifactId> + <scope>provided</scope> + </dependency> </dependencies> <build> diff --git a/extensions/kudu/runtime/src/main/java/org/apache/camel/quarkus/component/kudu/graal/EmptyByteBufStub.java b/extensions/kudu/runtime/src/main/java/org/apache/camel/quarkus/component/kudu/graal/EmptyByteBufStub.java new file mode 100644 index 0000000..0bd25f9 --- /dev/null +++ b/extensions/kudu/runtime/src/main/java/org/apache/camel/quarkus/component/kudu/graal/EmptyByteBufStub.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.kudu.graal; + +import java.nio.ByteBuffer; + +import org.apache.kudu.shaded.io.netty.util.internal.PlatformDependent; + +/** + * Adapted from + * https://github.com/quarkusio/quarkus/blob/master/extensions/netty/runtime/src/main/java/io/quarkus/netty/runtime/EmptyByteBufStub.java + */ +public final class EmptyByteBufStub { + private static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocateDirect(0); + private static final long EMPTY_BYTE_BUFFER_ADDRESS; + + static { + long emptyByteBufferAddress = 0; + try { + if (PlatformDependent.hasUnsafe()) { + emptyByteBufferAddress = PlatformDependent.directBufferAddress(EMPTY_BYTE_BUFFER); + } + } catch (Throwable t) { + // Ignore + } + EMPTY_BYTE_BUFFER_ADDRESS = emptyByteBufferAddress; + } + + public static ByteBuffer emptyByteBuffer() { + return EMPTY_BYTE_BUFFER; + } + + public static long emptyByteBufferAddress() { + return EMPTY_BYTE_BUFFER_ADDRESS; + } + + private EmptyByteBufStub() { + } +} diff --git a/extensions/kudu/runtime/src/main/java/org/apache/camel/quarkus/component/kudu/graal/NettySubstitutions.java b/extensions/kudu/runtime/src/main/java/org/apache/camel/quarkus/component/kudu/graal/NettySubstitutions.java new file mode 100644 index 0000000..6a498c6 --- /dev/null +++ b/extensions/kudu/runtime/src/main/java/org/apache/camel/quarkus/component/kudu/graal/NettySubstitutions.java @@ -0,0 +1,453 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.kudu.graal; + +import java.nio.ByteBuffer; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.cert.X509Certificate; +import java.util.Queue; +import java.util.concurrent.LinkedBlockingDeque; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLException; +import javax.net.ssl.TrustManagerFactory; + +import com.oracle.svm.core.annotate.Alias; +import com.oracle.svm.core.annotate.RecomputeFieldValue; +import com.oracle.svm.core.annotate.Substitute; +import com.oracle.svm.core.annotate.TargetClass; +import com.oracle.svm.core.jdk.JDK8OrEarlier; +import org.apache.kudu.shaded.io.netty.bootstrap.AbstractBootstrapConfig; +import org.apache.kudu.shaded.io.netty.bootstrap.ChannelFactory; +import org.apache.kudu.shaded.io.netty.buffer.ByteBufAllocator; +import org.apache.kudu.shaded.io.netty.channel.Channel; +import org.apache.kudu.shaded.io.netty.channel.ChannelFuture; +import org.apache.kudu.shaded.io.netty.channel.DefaultChannelPromise; +import org.apache.kudu.shaded.io.netty.handler.ssl.ApplicationProtocolConfig; +import org.apache.kudu.shaded.io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior; +import org.apache.kudu.shaded.io.netty.handler.ssl.CipherSuiteFilter; +import org.apache.kudu.shaded.io.netty.handler.ssl.ClientAuth; +import org.apache.kudu.shaded.io.netty.handler.ssl.JdkAlpnApplicationProtocolNegotiator; +import org.apache.kudu.shaded.io.netty.handler.ssl.JdkApplicationProtocolNegotiator; +import org.apache.kudu.shaded.io.netty.handler.ssl.SslContext; +import org.apache.kudu.shaded.io.netty.handler.ssl.SslProvider; +import org.apache.kudu.shaded.io.netty.util.concurrent.GlobalEventExecutor; +import org.apache.kudu.shaded.io.netty.util.internal.logging.InternalLoggerFactory; +import org.apache.kudu.shaded.io.netty.util.internal.logging.JdkLoggerFactory; + +/** + * This substitution avoid having loggers added to the build. + * Adapted from + * https://github.com/quarkusio/quarkus/blob/master/extensions/netty/runtime/src/main/java/io/quarkus/netty/runtime/graal/NettySubstitutions.java + */ +@TargetClass(className = "org.apache.kudu.shaded.io.netty.util.internal.logging.InternalLoggerFactory") +final class Target_io_netty_util_internal_logging_InternalLoggerFactory { + + @Substitute + private static InternalLoggerFactory newDefaultFactory(String name) { + return JdkLoggerFactory.INSTANCE; + } +} + +// SSL +// This whole section is mostly about removing static analysis references to openssl/tcnative + +@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.JdkSslServerContext") +final class Target_io_netty_handler_ssl_JdkSslServerContext { + + @Alias + Target_io_netty_handler_ssl_JdkSslServerContext(Provider provider, + X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory, + X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, + KeyManagerFactory keyManagerFactory, Iterable<String> ciphers, CipherSuiteFilter cipherFilter, + ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout, + ClientAuth clientAuth, String[] protocols, boolean startTls, + String keyStore) + throws SSLException { + } +} + +@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.JdkSslClientContext") +final class Target_io_netty_handler_ssl_JdkSslClientContext { + + @Alias + Target_io_netty_handler_ssl_JdkSslClientContext(Provider sslContextProvider, X509Certificate[] trustCertCollection, + TrustManagerFactory trustManagerFactory, X509Certificate[] keyCertChain, PrivateKey key, + String keyPassword, KeyManagerFactory keyManagerFactory, Iterable<String> ciphers, + CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, String[] protocols, + long sessionCacheSize, long sessionTimeout, String keyStoreType) + throws SSLException { + + } +} + +@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.SslHandler$SslEngineType") +final class Target_io_netty_handler_ssl_SslHandler$SslEngineType { + + @Alias + public static Target_io_netty_handler_ssl_SslHandler$SslEngineType JDK; + + @Substitute + static Target_io_netty_handler_ssl_SslHandler$SslEngineType forEngine(SSLEngine engine) { + return JDK; + } +} +// +//@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.JdkAlpnApplicationProtocolNegotiator$AlpnWrapper", onlyWith = JDK11OrLater.class) +//final class Target_io_netty_handler_ssl_JdkAlpnApplicationProtocolNegotiator_AlpnWrapper { +// @Substitute +// public SSLEngine wrapSslEngine(SSLEngine engine, ByteBufAllocator alloc, +// JdkApplicationProtocolNegotiator applicationNegotiator, boolean isServer) { +// return (SSLEngine) (Object) new Target_io_netty_handler_ssl_JdkAlpnSslEngine(engine, applicationNegotiator, isServer); +// } +// +//} + +@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.JdkAlpnApplicationProtocolNegotiator$AlpnWrapper", onlyWith = JDK8OrEarlier.class) +final class Target_io_netty_handler_ssl_JdkAlpnApplicationProtocolNegotiator_AlpnWrapperJava8 { + @Substitute + public SSLEngine wrapSslEngine(SSLEngine engine, ByteBufAllocator alloc, + JdkApplicationProtocolNegotiator applicationNegotiator, boolean isServer) { + if (Target_io_netty_handler_ssl_JettyAlpnSslEngine.isAvailable()) { + return isServer + ? (SSLEngine) (Object) Target_io_netty_handler_ssl_JettyAlpnSslEngine.newServerEngine(engine, + applicationNegotiator) + : (SSLEngine) (Object) Target_io_netty_handler_ssl_JettyAlpnSslEngine.newClientEngine(engine, + applicationNegotiator); + } + throw new RuntimeException("Unable to wrap SSLEngine of type " + engine.getClass().getName()); + } + +} + +@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.JettyAlpnSslEngine", onlyWith = JDK8OrEarlier.class) +final class Target_io_netty_handler_ssl_JettyAlpnSslEngine { + @Substitute + static boolean isAvailable() { + return false; + } + + @Substitute + static Target_io_netty_handler_ssl_JettyAlpnSslEngine newClientEngine(SSLEngine engine, + JdkApplicationProtocolNegotiator applicationNegotiator) { + return null; + } + + @Substitute + static Target_io_netty_handler_ssl_JettyAlpnSslEngine newServerEngine(SSLEngine engine, + JdkApplicationProtocolNegotiator applicationNegotiator) { + return null; + } +} +// +//@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.JdkAlpnSslEngine", onlyWith = JDK11OrLater.class) +//final class Target_io_netty_handler_ssl_JdkAlpnSslEngine { +// @Alias +// Target_io_netty_handler_ssl_JdkAlpnSslEngine(final SSLEngine engine, +// final JdkApplicationProtocolNegotiator applicationNegotiator, final boolean isServer) { +// +// } +//} + +@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.SslContext") +final class Target_io_netty_handler_ssl_SslContext { + + @Substitute + static SslContext newServerContextInternal(SslProvider provider, + Provider sslContextProvider, + X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory, + X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory, + Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, + long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls, + boolean enableOcsp, String keyStoreType) + throws SSLException { + + if (enableOcsp) { + throw new IllegalArgumentException("OCSP is not supported with this SslProvider: " + provider); + } + return (SslContext) (Object) new Target_io_netty_handler_ssl_JdkSslServerContext(sslContextProvider, + trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword, + keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, + clientAuth, protocols, startTls, keyStoreType); + } + + @Substitute + static SslContext newClientContextInternal( + SslProvider provider, + Provider sslContextProvider, + X509Certificate[] trustCert, TrustManagerFactory trustManagerFactory, + X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory, + Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, String[] protocols, + long sessionCacheSize, long sessionTimeout, boolean enableOcsp, String keyStoreType) throws SSLException { + if (enableOcsp) { + throw new IllegalArgumentException("OCSP is not supported with this SslProvider: " + provider); + } + return (SslContext) (Object) new Target_io_netty_handler_ssl_JdkSslClientContext(sslContextProvider, + trustCert, trustManagerFactory, keyCertChain, key, keyPassword, + keyManagerFactory, ciphers, cipherFilter, apn, protocols, sessionCacheSize, + sessionTimeout, keyStoreType); + } + +} + +@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.JdkDefaultApplicationProtocolNegotiator") +final class Target_io_netty_handler_ssl_JdkDefaultApplicationProtocolNegotiator { + + @Alias + public static Target_io_netty_handler_ssl_JdkDefaultApplicationProtocolNegotiator INSTANCE; +} + +@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.ssl.JdkSslContext") +final class Target_io_netty_handler_ssl_JdkSslContext { + + @Substitute + static JdkApplicationProtocolNegotiator toNegotiator(ApplicationProtocolConfig config, boolean isServer) { + if (config == null) { + return (JdkApplicationProtocolNegotiator) (Object) Target_io_netty_handler_ssl_JdkDefaultApplicationProtocolNegotiator.INSTANCE; + } + + switch (config.protocol()) { + case NONE: + return (JdkApplicationProtocolNegotiator) (Object) Target_io_netty_handler_ssl_JdkDefaultApplicationProtocolNegotiator.INSTANCE; + case ALPN: + if (isServer) { + // GRAAL RC9 bug: https://github.com/oracle/graal/issues/813 + // switch(config.selectorFailureBehavior()) { + // case FATAL_ALERT: + // return new JdkAlpnApplicationProtocolNegotiator(true, config.supportedProtocols()); + // case NO_ADVERTISE: + // return new JdkAlpnApplicationProtocolNegotiator(false, config.supportedProtocols()); + // default: + // throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ") + // .append(config.selectorFailureBehavior()).append(" failure behavior").toString()); + // } + SelectorFailureBehavior behavior = config.selectorFailureBehavior(); + if (behavior == SelectorFailureBehavior.FATAL_ALERT) + return new JdkAlpnApplicationProtocolNegotiator(true, config.supportedProtocols()); + else if (behavior == SelectorFailureBehavior.NO_ADVERTISE) + return new JdkAlpnApplicationProtocolNegotiator(false, config.supportedProtocols()); + else { + throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ") + .append(config.selectorFailureBehavior()).append(" failure behavior").toString()); + } + } else { + switch (config.selectedListenerFailureBehavior()) { + case ACCEPT: + return new JdkAlpnApplicationProtocolNegotiator(false, config.supportedProtocols()); + case FATAL_ALERT: + return new JdkAlpnApplicationProtocolNegotiator(true, config.supportedProtocols()); + default: + throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ") + .append(config.selectedListenerFailureBehavior()).append(" failure behavior").toString()); + } + } + default: + throw new UnsupportedOperationException( + new StringBuilder("JDK provider does not support ").append(config.protocol()).append(" protocol") + .toString()); + } + } + +} + +/* + * This one only prints exceptions otherwise we get a useless bogus + * exception message: https://github.com/eclipse-vertx/vert.x/issues/1657 + */ +@TargetClass(className = "org.apache.kudu.shaded.io.netty.bootstrap.AbstractBootstrap") +final class Target_io_netty_bootstrap_AbstractBootstrap { + + @Alias + private ChannelFactory channelFactory; + + @Alias + void init(Channel channel) throws Exception { + } + + @Alias + public AbstractBootstrapConfig config() { + return null; + } + + @Substitute + final ChannelFuture initAndRegister() { + Channel channel = null; + try { + channel = channelFactory.newChannel(); + init(channel); + } catch (Throwable t) { + // THE FIX IS HERE: + t.printStackTrace(); + if (channel != null) { + // channel can be null if newChannel crashed (eg SocketException("too many open files")) + channel.unsafe().closeForcibly(); + } + // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor + return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t); + } + + ChannelFuture regFuture = config().group().register(channel); + if (regFuture.cause() != null) { + if (channel.isRegistered()) { + channel.close(); + } else { + channel.unsafe().closeForcibly(); + } + } + + // If we are here and the promise is not failed, it's one of the following cases: + // 1) If we attempted registration from the event loop, the registration has been completed at this point. + // i.e. It's safe to attempt bind() or connect() now because the channel has been registered. + // 2) If we attempted registration from the other thread, the registration request has been successfully + // added to the event loop's task queue for later execution. + // i.e. It's safe to attempt bind() or connect() now: + // because bind() or connect() will be executed *after* the scheduled registration task is executed + // because register(), bind(), and connect() are all bound to the same thread. + + return regFuture; + + } +} + +@TargetClass(className = "org.apache.kudu.shaded.io.netty.channel.nio.NioEventLoop") +final class Target_io_netty_channel_nio_NioEventLoop { + + @Substitute + private static Queue<Runnable> newTaskQueue0(int maxPendingTasks) { + return new LinkedBlockingDeque<>(); + } +} + +@TargetClass(className = "org.apache.kudu.shaded.io.netty.buffer.AbstractReferenceCountedByteBuf") +final class Target_io_netty_buffer_AbstractReferenceCountedByteBuf { + + @Alias + @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FieldOffset, name = "refCnt") + private static long REFCNT_FIELD_OFFSET; +} + +@TargetClass(className = "org.apache.kudu.shaded.io.netty.util.AbstractReferenceCounted") +final class Target_io_netty_util_AbstractReferenceCounted { + + @Alias + @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FieldOffset, name = "refCnt") + private static long REFCNT_FIELD_OFFSET; +} + +// This class is runtime-initialized by NettyProcessor +final class Holder_io_netty_util_concurrent_ScheduledFutureTask { + static final long START_TIME = System.nanoTime(); +} + +@TargetClass(className = "org.apache.kudu.shaded.io.netty.util.concurrent.ScheduledFutureTask") +final class Target_io_netty_util_concurrent_ScheduledFutureTask { + + // The START_TIME field is kept but not used. + // All the accesses to it have been replaced with Holder_io_netty_util_concurrent_ScheduledFutureTask + + @Substitute + static long initialNanoTime() { + return Holder_io_netty_util_concurrent_ScheduledFutureTask.START_TIME; + } + + @Substitute + static long nanoTime() { + return System.nanoTime() - Holder_io_netty_util_concurrent_ScheduledFutureTask.START_TIME; + } + + @Alias + public long deadlineNanos() { + return 0; + } + + @Substitute + public long delayNanos(long currentTimeNanos) { + return Math.max(0, + deadlineNanos() - (currentTimeNanos - Holder_io_netty_util_concurrent_ScheduledFutureTask.START_TIME)); + } +} + +@TargetClass(className = "org.apache.kudu.shaded.io.netty.channel.ChannelHandlerMask") +final class Target_io_netty_channel_ChannelHandlerMask { + + // Netty tries to self-optimized itself, but it requires lots of reflection. We disable this behavior and avoid + // misleading DEBUG messages in the log. + @Substitute + private static boolean isSkippable(final Class<?> handlerType, final String methodName, final Class... paramTypes) { + return false; + } +} + +@TargetClass(className = "org.apache.kudu.shaded.io.netty.util.internal.NativeLibraryLoader") +final class Target_io_netty_util_internal_NativeLibraryLoader { + + // This method can trick GraalVM into thinking that Classloader#defineClass is getting called + @Substitute + static Class<?> tryToLoadClass(final ClassLoader loader, final Class<?> helper) + throws ClassNotFoundException { + return Class.forName(helper.getName(), false, loader); + } + +} + +@TargetClass(className = "org.apache.kudu.shaded.io.netty.buffer.EmptyByteBuf") +final class Target_io_netty_buffer_EmptyByteBuf { + + @Alias + @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset) + private static ByteBuffer EMPTY_BYTE_BUFFER; + + @Alias + @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset) + private static long EMPTY_BYTE_BUFFER_ADDRESS; + + @Substitute + public ByteBuffer nioBuffer() { + return EmptyByteBufStub.emptyByteBuffer(); + } + + @Substitute + public ByteBuffer[] nioBuffers() { + return new ByteBuffer[] { EmptyByteBufStub.emptyByteBuffer() }; + } + + @Substitute + public ByteBuffer internalNioBuffer(int index, int length) { + return EmptyByteBufStub.emptyByteBuffer(); + } + + @Substitute + public boolean hasMemoryAddress() { + return EmptyByteBufStub.emptyByteBufferAddress() != 0; + } + + @Substitute + public long memoryAddress() { + if (hasMemoryAddress()) { + return EmptyByteBufStub.emptyByteBufferAddress(); + } else { + throw new UnsupportedOperationException(); + } + } + +} + +class NettySubstitutions { + +} diff --git a/extensions/kudu/runtime/src/main/java/org/apache/camel/quarkus/component/kudu/graal/ZLibSubstitutions.java b/extensions/kudu/runtime/src/main/java/org/apache/camel/quarkus/component/kudu/graal/ZLibSubstitutions.java new file mode 100644 index 0000000..9e80749 --- /dev/null +++ b/extensions/kudu/runtime/src/main/java/org/apache/camel/quarkus/component/kudu/graal/ZLibSubstitutions.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.kudu.graal; + +import com.oracle.svm.core.annotate.Substitute; +import com.oracle.svm.core.annotate.TargetClass; +import org.apache.kudu.shaded.io.netty.handler.codec.compression.JdkZlibDecoder; +import org.apache.kudu.shaded.io.netty.handler.codec.compression.JdkZlibEncoder; +import org.apache.kudu.shaded.io.netty.handler.codec.compression.ZlibDecoder; +import org.apache.kudu.shaded.io.netty.handler.codec.compression.ZlibEncoder; +import org.apache.kudu.shaded.io.netty.handler.codec.compression.ZlibWrapper; + +/** + * This substitution avoid having jcraft zlib added to the build + * Adapted from + * https://github.com/quarkusio/quarkus/blob/master/extensions/netty/runtime/src/main/java/io/quarkus/netty/runtime/graal/ZLibSubstitutions.java + */ +@TargetClass(className = "org.apache.kudu.shaded.io.netty.handler.codec.compression.ZlibCodecFactory") +final class Target_io_netty_handler_codec_compression_ZlibCodecFactory { + + @Substitute + public static ZlibEncoder newZlibEncoder(int compressionLevel) { + return new JdkZlibEncoder(compressionLevel); + } + + @Substitute + public static ZlibEncoder newZlibEncoder(ZlibWrapper wrapper) { + return new JdkZlibEncoder(wrapper); + } + + @Substitute + public static ZlibEncoder newZlibEncoder(ZlibWrapper wrapper, int compressionLevel) { + return new JdkZlibEncoder(wrapper, compressionLevel); + } + + @Substitute + public static ZlibEncoder newZlibEncoder(ZlibWrapper wrapper, int compressionLevel, int windowBits, int memLevel) { + return new JdkZlibEncoder(wrapper, compressionLevel); + } + + @Substitute + public static ZlibEncoder newZlibEncoder(byte[] dictionary) { + return new JdkZlibEncoder(dictionary); + } + + @Substitute + public static ZlibEncoder newZlibEncoder(int compressionLevel, byte[] dictionary) { + return new JdkZlibEncoder(compressionLevel, dictionary); + } + + @Substitute + public static ZlibEncoder newZlibEncoder(int compressionLevel, int windowBits, int memLevel, byte[] dictionary) { + return new JdkZlibEncoder(compressionLevel, dictionary); + } + + @Substitute + public static ZlibDecoder newZlibDecoder() { + return new JdkZlibDecoder(); + } + + @Substitute + public static ZlibDecoder newZlibDecoder(ZlibWrapper wrapper) { + return new JdkZlibDecoder(wrapper); + } + + @Substitute + public static ZlibDecoder newZlibDecoder(byte[] dictionary) { + return new JdkZlibDecoder(dictionary); + } +} + +class ZLibSubstitutions { + +}