/* * JBoss, Home of Professional Open Source. * * Copyright 2013 Red Hat, Inc. and/or its affiliates, and individual * contributors as indicated by the @author tags. * * Licensed 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.xnio.ssl; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.net.Inet4Address; import java.net.InetSocketAddress; import java.net.URL; import java.nio.channels.Channel; import java.util.concurrent.CancellationException; import javax.net.ssl.SSLContext; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import org.xnio.ChannelListener; import org.xnio.IoFuture; import org.xnio.OptionMap; import org.xnio.Options; import org.xnio.Sequence; import org.xnio.StreamConnection; import org.xnio.Xnio; import org.xnio.channels.AcceptingChannel; import org.xnio.channels.BoundChannel; import org.xnio.channels.ConnectedSslStreamChannel; import org.xnio.channels.ConnectedStreamChannel; import org.xnio.mock.XnioIoThreadMock; import org.xnio.mock.XnioWorkerMock; /** * Test for {@link JsseXnioSsl}. * * @author <a href="mailto:frainone@redhat.com">Flavia Rainone</a> */ @SuppressWarnings("deprecation") public class JsseXnioSslTestCase { private static final String KEY_STORE_PROPERTY = "javax.net.ssl.keyStore"; private static final String KEY_STORE_PASSWORD_PROPERTY = "javax.net.ssl.keyStorePassword"; private static final String TRUST_STORE_PROPERTY = "javax.net.ssl.trustStore"; private static final String TRUST_STORE_PASSWORD_PROPERTY = "javax.net.ssl.trustStorePassword"; private static final String DEFAULT_KEY_STORE = "keystore.jks"; private static final String DEFAULT_KEY_STORE_PASSWORD = "apiTest"; private static final int SERVER_PORT = 23456; @BeforeClass public static void setKeyStoreAndTrustStore() { final URL storePath = JsseXnioSslTestCase.class.getClassLoader().getResource(DEFAULT_KEY_STORE); if (System.getProperty(KEY_STORE_PROPERTY) == null) { System.setProperty(KEY_STORE_PROPERTY, storePath.getFile()); } if (System.getProperty(KEY_STORE_PASSWORD_PROPERTY) == null) { System.setProperty(KEY_STORE_PASSWORD_PROPERTY, DEFAULT_KEY_STORE_PASSWORD); } if (System.getProperty(TRUST_STORE_PROPERTY) == null) { System.setProperty(TRUST_STORE_PROPERTY, storePath.getFile()); } if (System.getProperty(TRUST_STORE_PASSWORD_PROPERTY) == null) { System.setProperty(TRUST_STORE_PASSWORD_PROPERTY, DEFAULT_KEY_STORE_PASSWORD); } } private InetSocketAddress serverAddress; private Xnio xnio; private XnioWorkerMock worker; private XnioSsl xnioSsl; private XnioIoThreadMock threadMock; @Before public void init() throws Exception { serverAddress = new InetSocketAddress(Inet4Address.getByAddress(new byte[] { 127, 0, 0, 1 }), SERVER_PORT); xnio = Xnio.getInstance("xnio-mock", JsseXnioSslTestCase.class.getClassLoader()); worker = (XnioWorkerMock) xnio.createWorker(OptionMap.EMPTY); threadMock = worker.chooseThread(); threadMock.start(); xnioSsl = xnio.getSslProvider(OptionMap.EMPTY); } @After public void closeIoThread() { threadMock.closeIoThread(); } @Test public void testCreateSslConnectionServer() throws Exception { final TestChannelListener<AcceptingChannel<SslConnection>> openListener = new TestChannelListener<AcceptingChannel<SslConnection>>(); // IDEA thinks this is unchecked because of http://youtrack.jetbrains.net/issue/IDEA-59290 @SuppressWarnings("unchecked") final AcceptingChannel<? extends SslConnection> server = xnioSsl.createSslConnectionServer(worker, serverAddress, openListener, OptionMap.create(Options.REUSE_ADDRESSES, Boolean.TRUE, Options.WORKER_NAME, "dummy")); assertNotNull(server); // try accepting to make sure the listener is invoked assertNotNull(server.accept()); assertSame(server, openListener.getChannel()); assertEquals(serverAddress, server.getLocalAddress()); assertSame(worker, server.getWorker()); assertTrue(server.getOption(Options.REUSE_ADDRESSES)); assertEquals("dummy", server.getOption(Options.WORKER_NAME)); assertNull(server.getOption(Options.BROADCAST)); } @Test public void testCreateSslTcpServer() throws Exception { final TestChannelListener<AcceptingChannel<ConnectedSslStreamChannel>> openListener = new TestChannelListener<AcceptingChannel<ConnectedSslStreamChannel>>(); // IDEA thinks this is unchecked because of http://youtrack.jetbrains.net/issue/IDEA-59290 @SuppressWarnings("unchecked") final AcceptingChannel<? extends ConnectedStreamChannel> server = xnioSsl.createSslTcpServer(worker, serverAddress, openListener, OptionMap.create(Options.REUSE_ADDRESSES, Boolean.TRUE, Options.WORKER_NAME, "dummy")); assertNotNull(server); // try accepting to make sure the listener is correctly invoked final ConnectedStreamChannel channel = server.accept(); assertNotNull(channel); assertSame(server, openListener.getChannel()); assertSame(server, openListener.getChannel()); assertEquals(serverAddress, server.getLocalAddress()); assertSame(worker, server.getWorker()); assertTrue(server.getOption(Options.REUSE_ADDRESSES)); assertEquals("dummy", server.getOption(Options.WORKER_NAME)); assertNull(server.getOption(Options.BROADCAST)); } @Test public void testCreateSslConnectionServerWithDirectBuffers() throws Exception { //for (Provider p: Security.getProviders()) { // System.out.println("Provider " + p + " - " + p.getName()); //} //final TestListener<ConnectedStreamChannel> listener = new TestListener<ConnectedStreamChannel>(); xnioSsl = xnio.getSslProvider(OptionMap.create(Options.USE_DIRECT_BUFFERS, true)); // IDEA thinks this is unchecked because of http://youtrack.jetbrains.net/issue/IDEA-59290 @SuppressWarnings("unchecked") final AcceptingChannel<? extends SslConnection> server = xnioSsl.createSslConnectionServer(worker, serverAddress, null, OptionMap.create(Options.REUSE_ADDRESSES, Boolean.FALSE)); assertNotNull(server); final StreamConnection connection = server.accept(); assertNotNull(connection); // try calling the listener to make sure that openListener is invoked, i.e., testing that the openlistener is set correctly: assertEquals(serverAddress, server.getLocalAddress()); assertSame(worker, server.getWorker()); assertFalse(server.getOption(Options.REUSE_ADDRESSES)); assertNull(server.getOption(Options.WORKER_NAME)); } @Test public void testCreateSslTcpServerWithDirectBuffers() throws Exception { //for (Provider p: Security.getProviders()) { // System.out.println("Provider " + p + " - " + p.getName()); //} //final TestListener<ConnectedStreamChannel> listener = new TestListener<ConnectedStreamChannel>(); xnioSsl = xnio.getSslProvider(OptionMap.create(Options.USE_DIRECT_BUFFERS, true)); // IDEA thinks this is unchecked because of http://youtrack.jetbrains.net/issue/IDEA-59290 @SuppressWarnings("unchecked") final AcceptingChannel<? extends ConnectedStreamChannel> server = xnioSsl.createSslTcpServer(worker, serverAddress, null, OptionMap.create(Options.REUSE_ADDRESSES, Boolean.FALSE)); assertNotNull(server); ConnectedStreamChannel channel = server.accept(); assertNotNull(channel); // try calling the listener to make sure that openListener is invoked, i.e., testing that the openlistener is set correctly: assertEquals(serverAddress, server.getLocalAddress()); assertSame(worker, server.getWorker()); assertFalse(server.getOption(Options.REUSE_ADDRESSES)); assertNull(server.getOption(Options.WORKER_NAME)); } @Test public void connectSsl1() throws Exception { final TestChannelListener<StreamConnection> openListener = new TestChannelListener<StreamConnection>(); final IoFuture<? extends StreamConnection> ioFuture = xnioSsl.openSslConnection(worker, serverAddress, openListener, OptionMap.EMPTY); final StreamConnection connection = ioFuture.get(); assertNotNull(connection); assertSame(connection, openListener.getChannel()); assertSame(worker, connection.getWorker()); assertNotNull(connection.getLocalAddress()); assertEquals(serverAddress, connection.getPeerAddress()); assertNull(connection.getOption(Options.ALLOW_BLOCKING)); assertNull(connection.getOption(Options.FILE_ACCESS)); assertNull(connection.getOption(Options.RECEIVE_BUFFER)); assertNull(connection.getOption(Options.STACK_SIZE)); } @Test public void connectSsl2() throws Exception { final TestChannelListener<StreamConnection> openListener = new TestChannelListener<StreamConnection>(); final TestChannelListener<BoundChannel> bindListener = new TestChannelListener<BoundChannel>(); xnioSsl = xnio.getSslProvider(OptionMap.create(Options.SSL_PROTOCOL, "TLSv1.2")); final IoFuture<? extends StreamConnection> ioFuture = xnioSsl.openSslConnection(worker, serverAddress, openListener, bindListener, OptionMap.create(Options.KEEP_ALIVE, true)); final StreamConnection connection = ioFuture.get(); assertNotNull(connection); assertSame(connection, openListener.getChannel()); final BoundChannel boundChannel = bindListener.getChannel(); assertNotNull(boundChannel); assertSame(worker, connection.getWorker()); assertNotNull(connection.getLocalAddress()); assertSame(connection.getLocalAddress(), boundChannel.getLocalAddress()); assertEquals(serverAddress, connection.getPeerAddress()); assertTrue(connection.getOption(Options.KEEP_ALIVE)); assertTrue(boundChannel.getOption(Options.KEEP_ALIVE)); assertNull(connection.getOption(Options.ALLOW_BLOCKING)); assertNull(boundChannel.getOption(Options.ALLOW_BLOCKING)); assertNull(connection.getOption(Options.FILE_ACCESS)); assertNull(boundChannel.getOption(Options.FILE_ACCESS)); assertNull(connection.getOption(Options.RECEIVE_BUFFER)); assertNull(boundChannel.getOption(Options.RECEIVE_BUFFER)); assertNull(connection.getOption(Options.STACK_SIZE)); assertNull(boundChannel.getOption(Options.STACK_SIZE)); } @Test public void connectSsl3() throws Exception { final InetSocketAddress localAddress = new InetSocketAddress(500); final OptionMap.Builder builder = OptionMap.builder(); builder.set(Options.SSL_PROTOCOL, "TLSv1"); builder.set(Options.SSL_CLIENT_SESSION_CACHE_SIZE, 20000); builder.set(Options.SSL_CLIENT_SESSION_TIMEOUT, 80); builder.set(Options.SSL_SERVER_SESSION_CACHE_SIZE, 30000); builder.set(Options.SSL_SERVER_SESSION_TIMEOUT, 130); final TestChannelListener<StreamConnection> openListener = new TestChannelListener<StreamConnection>(); xnioSsl = xnio.getSslProvider(builder.getMap()); final IoFuture<? extends StreamConnection> ioFuture = xnioSsl.openSslConnection(worker, localAddress , serverAddress, openListener, OptionMap.create(Options.TCP_NODELAY, true)); final StreamConnection connection = ioFuture.get(); assertNotNull(connection); assertSame(connection, openListener.getChannel()); assertSame(worker, connection.getWorker()); assertEquals(localAddress, connection.getLocalAddress()); assertEquals(serverAddress, connection.getPeerAddress()); assertTrue(connection.getOption(Options.TCP_NODELAY)); } @Test @Ignore public void connectSsl4() throws Exception { final InetSocketAddress localAddress = new InetSocketAddress(600); final TestChannelListener<BoundChannel> bindListener = new TestChannelListener<BoundChannel>(); final TestChannelListener<StreamConnection> openListener = new TestChannelListener<StreamConnection>(); final String[] enabledCipherSuites = new String[] {"SSL_DH_anon_WITH_RC4_128_MD5", "TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", "SSL_RSA_WITH_RC4_128_MD5", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA", "nothing"}; final String[] validCipherSuites = new String[] {"SSL_DH_anon_WITH_RC4_128_MD5", "TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", "SSL_RSA_WITH_RC4_128_MD5", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA"}; final String[] enabledProtocols = new String[] {"SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2", "inexistent"}; final String[] validProtocols = new String[] {"SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"}; final OptionMap.Builder optionMapBuilder = OptionMap.builder(); optionMapBuilder.set(Options.SSL_ENABLE_SESSION_CREATION, false); optionMapBuilder.set(Options.SSL_ENABLED_CIPHER_SUITES, Sequence.of(enabledCipherSuites)); optionMapBuilder.set(Options.MULTICAST, true); optionMapBuilder.set(Options.READ_TIMEOUT, 1000); optionMapBuilder.set(Options.SSL_ENABLED_PROTOCOLS, Sequence.of(enabledProtocols)); optionMapBuilder.set(Options.SSL_STARTTLS, true); final IoFuture<? extends StreamConnection> ioFuture = xnioSsl.openSslConnection(worker, localAddress, serverAddress, openListener, bindListener, optionMapBuilder.getMap()); final StreamConnection connection = ioFuture.get(); assertNotNull(connection); final BoundChannel boundChannel = bindListener.getChannel(); assertNotNull(boundChannel); assertSame(connection, openListener.getChannel()); assertSame(worker, connection.getWorker()); assertEquals(localAddress, connection.getLocalAddress()); assertEquals(localAddress, boundChannel.getLocalAddress()); assertTrue(connection.getOption(Options.MULTICAST)); assertTrue(boundChannel.getOption(Options.MULTICAST)); assertEquals(1000, (int) connection.getOption(Options.READ_TIMEOUT)); assertEquals(1000, (int) boundChannel.getOption(Options.READ_TIMEOUT)); } @Test public void connectSslChannel1() throws Exception { final TestChannelListener<ConnectedSslStreamChannel> openListener = new TestChannelListener<ConnectedSslStreamChannel>(); final IoFuture<? extends ConnectedStreamChannel> ioFuture = xnioSsl.connectSsl(worker, serverAddress, openListener, OptionMap.EMPTY); final ConnectedStreamChannel channel = ioFuture.get(); assertNotNull(channel); assertSame(channel, openListener.getChannel()); assertSame(worker, channel.getWorker()); assertNotNull(channel.getLocalAddress()); assertEquals(serverAddress, channel.getPeerAddress()); assertNull(channel.getOption(Options.ALLOW_BLOCKING)); assertNull(channel.getOption(Options.FILE_ACCESS)); assertNull(channel.getOption(Options.RECEIVE_BUFFER)); assertNull(channel.getOption(Options.STACK_SIZE)); } @Test public void connectSslChannel2() throws Exception { final TestChannelListener<ConnectedSslStreamChannel> openListener = new TestChannelListener<ConnectedSslStreamChannel>(); final TestChannelListener<BoundChannel> bindListener = new TestChannelListener<BoundChannel>(); xnioSsl = xnio.getSslProvider(OptionMap.create(Options.SSL_PROTOCOL, "TLSv1.2")); final IoFuture<? extends ConnectedStreamChannel> ioFuture = xnioSsl.connectSsl(worker, serverAddress, openListener, bindListener, OptionMap.create(Options.KEEP_ALIVE, true)); final ConnectedStreamChannel channel = ioFuture.get(); assertNotNull(channel); assertSame(channel, openListener.getChannel()); final BoundChannel boundChannel = bindListener.getChannel(); assertNotNull(boundChannel); assertSame(worker, channel.getWorker()); assertNotNull(channel.getLocalAddress()); assertSame(channel.getLocalAddress(), boundChannel.getLocalAddress()); assertEquals(serverAddress, channel.getPeerAddress()); assertTrue(channel.getOption(Options.KEEP_ALIVE)); assertTrue(boundChannel.getOption(Options.KEEP_ALIVE)); assertNull(channel.getOption(Options.ALLOW_BLOCKING)); assertNull(boundChannel.getOption(Options.ALLOW_BLOCKING)); assertNull(channel.getOption(Options.FILE_ACCESS)); assertNull(boundChannel.getOption(Options.FILE_ACCESS)); assertNull(channel.getOption(Options.RECEIVE_BUFFER)); assertNull(boundChannel.getOption(Options.RECEIVE_BUFFER)); assertNull(channel.getOption(Options.STACK_SIZE)); assertNull(boundChannel.getOption(Options.STACK_SIZE)); } @Test public void connectSslChannel3() throws Exception { final InetSocketAddress localAddress = new InetSocketAddress(500); final OptionMap.Builder builder = OptionMap.builder(); builder.set(Options.SSL_PROTOCOL, "TLSv1"); builder.set(Options.SSL_CLIENT_SESSION_CACHE_SIZE, 20000); builder.set(Options.SSL_CLIENT_SESSION_TIMEOUT, 80); builder.set(Options.SSL_SERVER_SESSION_CACHE_SIZE, 30000); builder.set(Options.SSL_SERVER_SESSION_TIMEOUT, 130); final TestChannelListener<ConnectedSslStreamChannel> openListener = new TestChannelListener<ConnectedSslStreamChannel>(); xnioSsl = xnio.getSslProvider(builder.getMap()); final IoFuture<? extends ConnectedStreamChannel> ioFuture = xnioSsl.connectSsl(worker, localAddress , serverAddress, openListener, OptionMap.create(Options.TCP_NODELAY, true)); final ConnectedStreamChannel channel = ioFuture.get(); assertNotNull(channel); assertSame(channel, openListener.getChannel()); assertSame(worker, channel.getWorker()); assertEquals(localAddress, channel.getLocalAddress()); assertEquals(serverAddress, channel.getPeerAddress()); assertTrue(channel.getOption(Options.TCP_NODELAY)); } @Test public void connectSslChannel4() throws Exception { final InetSocketAddress localAddress = new InetSocketAddress(600); final TestChannelListener<BoundChannel> bindListener = new TestChannelListener<BoundChannel>(); final TestChannelListener<ConnectedSslStreamChannel> openListener = new TestChannelListener<ConnectedSslStreamChannel>(); final String[] enabledCipherSuites = new String[] {"SSL_DH_anon_WITH_RC4_128_MD5", "TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", "SSL_RSA_WITH_RC4_128_MD5", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA", "nothing"}; final String[] validCipherSuites = new String[] {"SSL_DH_anon_WITH_RC4_128_MD5", "TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", "SSL_RSA_WITH_RC4_128_MD5", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA"}; final String[] enabledProtocols = new String[] {"SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2", "inexistent"}; final String[] validProtocols = new String[] {"SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"}; final OptionMap.Builder optionMapBuilder = OptionMap.builder(); optionMapBuilder.set(Options.SSL_ENABLE_SESSION_CREATION, false); optionMapBuilder.set(Options.SSL_ENABLED_CIPHER_SUITES, Sequence.of(enabledCipherSuites)); optionMapBuilder.set(Options.MULTICAST, true); optionMapBuilder.set(Options.READ_TIMEOUT, 1000); optionMapBuilder.set(Options.SSL_ENABLED_PROTOCOLS, Sequence.of(enabledProtocols)); optionMapBuilder.set(Options.SSL_STARTTLS, true); final IoFuture<? extends ConnectedStreamChannel> ioFuture = xnioSsl.connectSsl(worker, localAddress, serverAddress, openListener, bindListener, optionMapBuilder.getMap()); final ConnectedStreamChannel channel = ioFuture.get(); assertNotNull(channel); final BoundChannel boundChannel = bindListener.getChannel(); assertNotNull(boundChannel); assertSame(channel, openListener.getChannel()); assertSame(worker, channel.getWorker()); assertEquals(localAddress, channel.getLocalAddress()); assertEquals(localAddress, boundChannel.getLocalAddress()); assertTrue(channel.getOption(Options.MULTICAST)); assertTrue(boundChannel.getOption(Options.MULTICAST)); assertEquals(1000, (int) channel.getOption(Options.READ_TIMEOUT)); assertEquals(1000, (int) boundChannel.getOption(Options.READ_TIMEOUT)); } @Test public void failedConnection() throws Exception { worker.failConnection(); final IoFuture<? extends StreamConnection> connectionFuture = xnioSsl.openSslConnection(worker, new InetSocketAddress(Inet4Address.getByAddress(new byte[] { 127, 0, 0, 1 }), SERVER_PORT), new InetSocketAddress(Inet4Address.getByAddress(new byte[] { 127, 0, 0, 1 }), SERVER_PORT), null, null, OptionMap.EMPTY); boolean failed = false; try { connectionFuture.get(); } catch (IOException e) { failed = true; } assertTrue(failed); failed = false; final IoFuture<? extends ConnectedStreamChannel> channelFuture = xnioSsl.connectSsl(worker, new InetSocketAddress(Inet4Address.getByAddress(new byte[] { 127, 0, 0, 1 }), SERVER_PORT), new InetSocketAddress(Inet4Address.getByAddress(new byte[] { 127, 0, 0, 1 }), SERVER_PORT), null, null, OptionMap.EMPTY); try { channelFuture.get(); } catch (IOException e) { failed = true; } assertTrue(failed); } @Test public void cancelledConnection() throws Exception { worker.cancelConnection(); final IoFuture<? extends StreamConnection> connectionFuture = xnioSsl.openSslConnection(worker, new InetSocketAddress(Inet4Address.getByAddress(new byte[] { 127, 0, 0, 1 }), SERVER_PORT), new InetSocketAddress(Inet4Address.getByAddress(new byte[] { 127, 0, 0, 1 }), SERVER_PORT), null, null, OptionMap.EMPTY); boolean cancelled = false; try { connectionFuture.get(); } catch (CancellationException e) { cancelled = true; } assertTrue(cancelled); cancelled = false; final IoFuture<? extends ConnectedStreamChannel> channelFuture = xnioSsl.connectSsl(worker, new InetSocketAddress(Inet4Address.getByAddress(new byte[] { 127, 0, 0, 1 }), SERVER_PORT), new InetSocketAddress(Inet4Address.getByAddress(new byte[] { 127, 0, 0, 1 }), SERVER_PORT), null, null, OptionMap.EMPTY); try { channelFuture.get(); } catch (CancellationException e) { cancelled = true; } assertTrue(cancelled); } @Test public void getSslContext() throws Exception { final Xnio xnio = Xnio.getInstance("xnio-mock", JsseXnioSslTestCase.class.getClassLoader()); final JsseXnioSsl xnioSsl = (JsseXnioSsl) xnio.getSslProvider(OptionMap.EMPTY); SSLContext context = xnioSsl.getSslContext(); assertNotNull(context); } private static class TestChannelListener<C extends Channel> implements ChannelListener<C> { private C channel; @Override public void handleEvent(C channel) { this.channel = channel; } public C getChannel() { return channel; } } }