You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pp...@apache.org on 2020/09/01 14:05:21 UTC
[camel-quarkus] branch camel-master updated: Fix #1664 KuduIT fails
with Camel 3.5.0
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 <pp...@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 {
+
+}