Skip to content

Commit f729f2e

Browse files
authored
Merge pull request #634 from michael-simons/feature/improve-shaded-netty-native
Add support for native compilation.
2 parents dbeed1d + b03bc89 commit f729f2e

File tree

6 files changed

+459
-0
lines changed

6 files changed

+459
-0
lines changed

driver/pom.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@
7878
<groupId>io.projectreactor</groupId>
7979
<artifactId>reactor-test</artifactId>
8080
</dependency>
81+
<dependency>
82+
<groupId>com.oracle.substratevm</groupId>
83+
<artifactId>svm</artifactId>
84+
</dependency>
8185
</dependencies>
8286

8387
<build>
@@ -232,6 +236,14 @@
232236
<transformers>
233237
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
234238
</transformers>
239+
<filters>
240+
<filter>
241+
<artifact>io.netty:*</artifact>
242+
<excludes>
243+
<exclude>META-INF/native-image/**</exclude>
244+
</excludes>
245+
</filter>
246+
</filters>
235247
<shadeTestJar>true</shadeTestJar>
236248
<createSourcesJar>true</createSourcesJar>
237249
</configuration>
Lines changed: 312 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
/*
2+
* Copyright (c) 2002-2019 "Neo4j,"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.neo4j.driver.internal.svm;
20+
21+
import com.oracle.svm.core.annotate.Alias;
22+
import com.oracle.svm.core.annotate.Substitute;
23+
import com.oracle.svm.core.annotate.TargetClass;
24+
import com.oracle.svm.core.jdk.JDK11OrLater;
25+
26+
import java.security.PrivateKey;
27+
import java.security.Provider;
28+
import java.security.cert.X509Certificate;
29+
import java.util.Queue;
30+
import java.util.concurrent.LinkedBlockingDeque;
31+
import javax.net.ssl.KeyManagerFactory;
32+
import javax.net.ssl.SSLEngine;
33+
import javax.net.ssl.SSLException;
34+
import javax.net.ssl.TrustManagerFactory;
35+
36+
import io.netty.bootstrap.AbstractBootstrapConfig;
37+
import io.netty.bootstrap.ChannelFactory;
38+
import io.netty.buffer.ByteBufAllocator;
39+
import io.netty.channel.Channel;
40+
import io.netty.channel.ChannelFuture;
41+
import io.netty.channel.DefaultChannelPromise;
42+
import io.netty.handler.ssl.ApplicationProtocolConfig;
43+
import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior;
44+
import io.netty.handler.ssl.CipherSuiteFilter;
45+
import io.netty.handler.ssl.ClientAuth;
46+
import io.netty.handler.ssl.JdkAlpnApplicationProtocolNegotiator;
47+
import io.netty.handler.ssl.JdkApplicationProtocolNegotiator;
48+
import io.netty.handler.ssl.SslContext;
49+
import io.netty.handler.ssl.SslProvider;
50+
import io.netty.util.concurrent.GlobalEventExecutor;
51+
import io.netty.util.internal.logging.InternalLoggerFactory;
52+
import io.netty.util.internal.logging.JdkLoggerFactory;
53+
54+
/**
55+
* This substitution avoid having loggers added to the build
56+
*/
57+
@TargetClass(className = "io.netty.util.internal.logging.InternalLoggerFactory")
58+
final class Target_io_netty_util_internal_logging_InternalLoggerFactory {
59+
60+
@Substitute
61+
private static InternalLoggerFactory newDefaultFactory( String name) {
62+
return JdkLoggerFactory.INSTANCE;
63+
}
64+
}
65+
66+
// SSL
67+
// This whole section is mostly about removing static analysis references to openssl/tcnative
68+
69+
@TargetClass(className = "io.netty.handler.ssl.JdkSslServerContext")
70+
final class Target_io_netty_handler_ssl_JdkSslServerContext {
71+
72+
@Alias
73+
Target_io_netty_handler_ssl_JdkSslServerContext( Provider provider,
74+
X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
75+
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword,
76+
KeyManagerFactory keyManagerFactory, Iterable<String> ciphers, CipherSuiteFilter cipherFilter,
77+
ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout,
78+
ClientAuth clientAuth, String[] protocols, boolean startTls,
79+
String keyStore)
80+
throws SSLException
81+
{
82+
}
83+
}
84+
85+
@TargetClass(className = "io.netty.handler.ssl.JdkSslClientContext")
86+
final class Target_io_netty_handler_ssl_JdkSslClientContext {
87+
88+
@Alias
89+
Target_io_netty_handler_ssl_JdkSslClientContext( Provider sslContextProvider,
90+
X509Certificate[] trustCertCollection,
91+
TrustManagerFactory trustManagerFactory, X509Certificate[] keyCertChain, PrivateKey key,
92+
String keyPassword, KeyManagerFactory keyManagerFactory, Iterable<String> ciphers,
93+
CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, String[] protocols,
94+
long sessionCacheSize, long sessionTimeout, String keyStoreType)
95+
throws SSLException
96+
{
97+
98+
}
99+
}
100+
101+
@TargetClass(className = "io.netty.handler.ssl.SslHandler$SslEngineType")
102+
final class Target_io_netty_handler_ssl_SslHandler$SslEngineType {
103+
104+
@Alias
105+
public static Target_io_netty_handler_ssl_SslHandler$SslEngineType JDK;
106+
107+
@Substitute
108+
static Target_io_netty_handler_ssl_SslHandler$SslEngineType forEngine( SSLEngine engine) {
109+
return JDK;
110+
}
111+
}
112+
113+
@TargetClass(className = "io.netty.handler.ssl.JdkAlpnApplicationProtocolNegotiator$AlpnWrapper", onlyWith = JDK11OrLater.class)
114+
final class Target_io_netty_handler_ssl_JdkAlpnApplicationProtocolNegotiator_AlpnWrapper {
115+
@Substitute
116+
@SuppressWarnings( "deprecation" )
117+
public SSLEngine wrapSslEngine( SSLEngine engine, ByteBufAllocator alloc,
118+
JdkApplicationProtocolNegotiator applicationNegotiator, boolean isServer) {
119+
return (SSLEngine) (Object) new Target_io_netty_handler_ssl_Java9SslEngine(
120+
engine, applicationNegotiator, isServer);
121+
}
122+
123+
}
124+
125+
@TargetClass(className = "io.netty.handler.ssl.Java9SslEngine", onlyWith = JDK11OrLater.class)
126+
final class Target_io_netty_handler_ssl_Java9SslEngine {
127+
@Alias
128+
@SuppressWarnings( "deprecation" )
129+
Target_io_netty_handler_ssl_Java9SslEngine(final SSLEngine engine,
130+
final JdkApplicationProtocolNegotiator applicationNegotiator, final boolean isServer) {
131+
132+
}
133+
}
134+
135+
@TargetClass(className = "io.netty.handler.ssl.SslContext")
136+
final class Target_io_netty_handler_ssl_SslContext {
137+
138+
@Substitute
139+
static SslContext newServerContextInternal(SslProvider provider,
140+
Provider sslContextProvider,
141+
X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory,
142+
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
143+
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
144+
long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls,
145+
boolean enableOcsp, String keyStoreType)
146+
throws SSLException
147+
{
148+
149+
if (enableOcsp) {
150+
throw new IllegalArgumentException("OCSP is not supported with this SslProvider: " + provider);
151+
}
152+
return (SslContext) (Object) new Target_io_netty_handler_ssl_JdkSslServerContext(
153+
sslContextProvider,
154+
trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword,
155+
keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout,
156+
clientAuth, protocols, startTls, keyStoreType);
157+
}
158+
159+
@Substitute
160+
static SslContext newClientContextInternal(
161+
SslProvider provider,
162+
Provider sslContextProvider,
163+
X509Certificate[] trustCert, TrustManagerFactory trustManagerFactory,
164+
X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory,
165+
Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, String[] protocols,
166+
long sessionCacheSize, long sessionTimeout, boolean enableOcsp, String keyStoreType) throws SSLException
167+
{
168+
if (enableOcsp) {
169+
throw new IllegalArgumentException("OCSP is not supported with this SslProvider: " + provider);
170+
}
171+
return (SslContext) (Object) new Target_io_netty_handler_ssl_JdkSslClientContext(
172+
sslContextProvider,
173+
trustCert, trustManagerFactory, keyCertChain, key, keyPassword,
174+
keyManagerFactory, ciphers, cipherFilter, apn, protocols, sessionCacheSize,
175+
sessionTimeout, keyStoreType);
176+
}
177+
178+
}
179+
180+
@TargetClass(className = "io.netty.handler.ssl.JdkDefaultApplicationProtocolNegotiator")
181+
final class Target_io_netty_handler_ssl_JdkDefaultApplicationProtocolNegotiator {
182+
183+
@Alias
184+
public static Target_io_netty_handler_ssl_JdkDefaultApplicationProtocolNegotiator INSTANCE;
185+
}
186+
187+
@TargetClass(className = "io.netty.handler.ssl.JdkSslContext")
188+
final class Target_io_netty_handler_ssl_JdkSslContext {
189+
190+
@Substitute
191+
static JdkApplicationProtocolNegotiator toNegotiator(ApplicationProtocolConfig config, boolean isServer) {
192+
if (config == null) {
193+
return (JdkApplicationProtocolNegotiator) (Object) Target_io_netty_handler_ssl_JdkDefaultApplicationProtocolNegotiator.INSTANCE;
194+
}
195+
196+
switch (config.protocol()) {
197+
case NONE:
198+
return (JdkApplicationProtocolNegotiator) (Object) Target_io_netty_handler_ssl_JdkDefaultApplicationProtocolNegotiator.INSTANCE;
199+
case ALPN:
200+
if (isServer) {
201+
// GRAAL RC9 bug: https://github.com/oracle/graal/issues/813
202+
// switch(config.selectorFailureBehavior()) {
203+
// case FATAL_ALERT:
204+
// return new JdkAlpnApplicationProtocolNegotiator(true, config.supportedProtocols());
205+
// case NO_ADVERTISE:
206+
// return new JdkAlpnApplicationProtocolNegotiator(false, config.supportedProtocols());
207+
// default:
208+
// throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ")
209+
// .append(config.selectorFailureBehavior()).append(" failure behavior").toString());
210+
// }
211+
SelectorFailureBehavior behavior = config.selectorFailureBehavior();
212+
if (behavior == SelectorFailureBehavior.FATAL_ALERT)
213+
return new JdkAlpnApplicationProtocolNegotiator(true, config.supportedProtocols());
214+
else if (behavior == SelectorFailureBehavior.NO_ADVERTISE)
215+
return new JdkAlpnApplicationProtocolNegotiator(false, config.supportedProtocols());
216+
else {
217+
throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ")
218+
.append(config.selectorFailureBehavior()).append(" failure behavior").toString());
219+
}
220+
} else {
221+
switch (config.selectedListenerFailureBehavior()) {
222+
case ACCEPT:
223+
return new JdkAlpnApplicationProtocolNegotiator(false, config.supportedProtocols());
224+
case FATAL_ALERT:
225+
return new JdkAlpnApplicationProtocolNegotiator(true, config.supportedProtocols());
226+
default:
227+
throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ")
228+
.append(config.selectedListenerFailureBehavior()).append(" failure behavior")
229+
.toString());
230+
}
231+
}
232+
default:
233+
throw new UnsupportedOperationException(
234+
new StringBuilder("JDK provider does not support ").append(config.protocol()).append(" protocol")
235+
.toString());
236+
}
237+
}
238+
239+
}
240+
241+
/*
242+
* This one only prints exceptions otherwise we get a useless bogus
243+
* exception message: https://github.com/eclipse-vertx/vert.x/issues/1657
244+
*/
245+
@TargetClass(className = "io.netty.bootstrap.AbstractBootstrap")
246+
final class Target_io_netty_bootstrap_AbstractBootstrap {
247+
248+
@Alias
249+
private ChannelFactory channelFactory;
250+
251+
@Alias
252+
void init(Channel channel) throws Exception
253+
{
254+
}
255+
256+
@Alias
257+
public AbstractBootstrapConfig config() {
258+
return null;
259+
}
260+
261+
@Substitute
262+
final ChannelFuture initAndRegister() {
263+
Channel channel = null;
264+
try {
265+
channel = channelFactory.newChannel();
266+
init(channel);
267+
} catch ( Throwable t) {
268+
// THE FIX IS HERE:
269+
t.printStackTrace();
270+
if (channel != null) {
271+
// channel can be null if newChannel crashed (eg SocketException("too many open files"))
272+
channel.unsafe().closeForcibly();
273+
}
274+
// as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
275+
return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
276+
}
277+
278+
ChannelFuture regFuture = config().group().register(channel);
279+
if (regFuture.cause() != null) {
280+
if (channel.isRegistered()) {
281+
channel.close();
282+
} else {
283+
channel.unsafe().closeForcibly();
284+
}
285+
}
286+
287+
// If we are here and the promise is not failed, it's one of the following cases:
288+
// 1) If we attempted registration from the event loop, the registration has been completed at this point.
289+
// i.e. It's safe to attempt bind() or connect() now because the channel has been registered.
290+
// 2) If we attempted registration from the other thread, the registration request has been successfully
291+
// added to the event loop's task queue for later execution.
292+
// i.e. It's safe to attempt bind() or connect() now:
293+
// because bind() or connect() will be executed *after* the scheduled registration task is executed
294+
// because register(), bind(), and connect() are all bound to the same thread.
295+
296+
return regFuture;
297+
298+
}
299+
}
300+
301+
@TargetClass(className = "io.netty.channel.nio.NioEventLoop")
302+
final class Target_io_netty_channel_nio_NioEventLoop {
303+
304+
@Substitute
305+
private static Queue<Runnable> newTaskQueue0(int maxPendingTasks) {
306+
return new LinkedBlockingDeque<>();
307+
}
308+
}
309+
310+
class NettySubstitutions {
311+
312+
}

0 commit comments

Comments
 (0)