Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java
38853 views
/*1* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223//24// Please run in othervm mode. SunJSSE does not support dynamic system25// properties, no way to re-use system properties in samevm/agentvm mode.26//2728/*29* @test30* @bug 8161106 817032931* @summary Improve SSLSocket test template32* @run main/othervm SSLSocketTemplate33*/3435import java.io.ByteArrayInputStream;36import java.io.InputStream;37import java.io.IOException;38import java.io.OutputStream;39import javax.net.ssl.KeyManagerFactory;40import javax.net.ssl.SSLContext;41import javax.net.ssl.SSLServerSocket;42import javax.net.ssl.SSLServerSocketFactory;43import javax.net.ssl.SSLSocket;44import javax.net.ssl.SSLSocketFactory;45import javax.net.ssl.TrustManagerFactory;46import java.net.InetSocketAddress;47import java.net.SocketTimeoutException;48import java.security.KeyStore;49import java.security.PrivateKey;50import java.security.KeyFactory;51import java.security.cert.Certificate;52import java.security.cert.CertificateFactory;53import java.security.spec.PKCS8EncodedKeySpec;54import java.util.Base64;5556import java.util.concurrent.CountDownLatch;57import java.util.concurrent.TimeUnit;5859/**60* Template to help speed your client/server tests.61*62* Two examples that use this template:63* test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java64* test/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java65*/66public class SSLSocketTemplate {6768/*69* ==================70* Run the test case.71*/72public static void main(String[] args) throws Exception {73(new SSLSocketTemplate()).run();74}7576/*77* Run the test case.78*/79public void run() throws Exception {80bootup();81}8283/*84* Define the server side application of the test for the specified socket.85*/86protected void runServerApplication(SSLSocket socket) throws Exception {87// here comes the test logic88InputStream sslIS = socket.getInputStream();89OutputStream sslOS = socket.getOutputStream();9091sslIS.read();92sslOS.write(85);93sslOS.flush();94}9596/*97* Define the client side application of the test for the specified socket.98* This method is used if the returned value of99* isCustomizedClientConnection() is false.100*101* @param socket may be null is no client socket is generated.102*103* @see #isCustomizedClientConnection()104*/105protected void runClientApplication(SSLSocket socket) throws Exception {106InputStream sslIS = socket.getInputStream();107OutputStream sslOS = socket.getOutputStream();108109sslOS.write(280);110sslOS.flush();111sslIS.read();112}113114/*115* Define the client side application of the test for the specified116* server port. This method is used if the returned value of117* isCustomizedClientConnection() is true.118*119* Note that the client need to connect to the server port by itself120* for the actual message exchange.121*122* @see #isCustomizedClientConnection()123*/124protected void runClientApplication(int serverPort) throws Exception {125// blank126}127128/*129* Create an instance of SSLContext for client use.130*/131protected SSLContext createClientSSLContext() throws Exception {132return createSSLContext(trustedCertStrs,133endEntityCertStrs, endEntityPrivateKeys,134endEntityPrivateKeyAlgs,135endEntityPrivateKeyNames,136getClientContextParameters());137}138139/*140* Create an instance of SSLContext for server use.141*/142protected SSLContext createServerSSLContext() throws Exception {143return createSSLContext(trustedCertStrs,144endEntityCertStrs, endEntityPrivateKeys,145endEntityPrivateKeyAlgs,146endEntityPrivateKeyNames,147getServerContextParameters());148}149150/*151* The parameters used to configure SSLContext.152*/153protected static final class ContextParameters {154final String contextProtocol;155final String tmAlgorithm;156final String kmAlgorithm;157158ContextParameters(String contextProtocol,159String tmAlgorithm, String kmAlgorithm) {160161this.contextProtocol = contextProtocol;162this.tmAlgorithm = tmAlgorithm;163this.kmAlgorithm = kmAlgorithm;164}165}166167/*168* Get the client side parameters of SSLContext.169*/170protected ContextParameters getClientContextParameters() {171return new ContextParameters("TLS", "PKIX", "NewSunX509");172}173174/*175* Get the server side parameters of SSLContext.176*/177protected ContextParameters getServerContextParameters() {178return new ContextParameters("TLS", "PKIX", "NewSunX509");179}180181/*182* Does the client side use customized connection other than183* explicit Socket.connect(), for example, URL.openConnection()?184*/185protected boolean isCustomizedClientConnection() {186return false;187}188189/*190* Configure the client side socket.191*/192protected void configureClientSocket(SSLSocket socket) {193}194195/*196* Configure the server side socket.197*/198protected void configureServerSocket(SSLServerSocket socket) {199}200201/*202* =============================================203* Define the client and server side operations.204*205* If the client or server is doing some kind of object creation206* that the other side depends on, and that thread prematurely207* exits, you may experience a hang. The test harness will208* terminate all hung threads after its timeout has expired,209* currently 3 minutes by default, but you might try to be210* smart about it....211*/212213/*214* Is the server ready to serve?215*/216private final CountDownLatch serverCondition = new CountDownLatch(1);217218/*219* Is the client ready to handshake?220*/221private final CountDownLatch clientCondition = new CountDownLatch(1);222223/*224* What's the server port? Use any free port by default225*/226private volatile int serverPort = 0;227228/*229* Define the server side of the test.230*/231private void doServerSide() throws Exception {232// kick start the server side service233SSLContext context = createServerSSLContext();234SSLServerSocketFactory sslssf = context.getServerSocketFactory();235SSLServerSocket sslServerSocket =236(SSLServerSocket)sslssf.createServerSocket(serverPort);237configureServerSocket(sslServerSocket);238serverPort = sslServerSocket.getLocalPort();239240// Signal the client, the server is ready to accept connection.241serverCondition.countDown();242243// Try to accept a connection in 30 seconds.244SSLSocket sslSocket;245try {246sslServerSocket.setSoTimeout(30000);247sslSocket = (SSLSocket)sslServerSocket.accept();248} catch (SocketTimeoutException ste) {249// Ignore the test case if no connection within 30 seconds.250System.out.println(251"No incoming client connection in 30 seconds. " +252"Ignore in server side.");253return;254} finally {255sslServerSocket.close();256}257258// handle the connection259try {260// Is it the expected client connection?261//262// Naughty test cases or third party routines may try to263// connection to this server port unintentionally. In264// order to mitigate the impact of unexpected client265// connections and avoid intermittent failure, it should266// be checked that the accepted connection is really linked267// to the expected client.268boolean clientIsReady =269clientCondition.await(30L, TimeUnit.SECONDS);270271if (clientIsReady) {272// Run the application in server side.273runServerApplication(sslSocket);274} else { // Otherwise, ignore275// We don't actually care about plain socket connections276// for TLS communication testing generally. Just ignore277// the test if the accepted connection is not linked to278// the expected client or the client connection timeout279// in 30 seconds.280System.out.println(281"The client is not the expected one or timeout. " +282"Ignore in server side.");283}284} finally {285sslSocket.close();286}287}288289/*290* Define the client side of the test.291*/292private void doClientSide() throws Exception {293294// Wait for server to get started.295//296// The server side takes care of the issue if the server cannot297// get started in 90 seconds. The client side would just ignore298// the test case if the serer is not ready.299boolean serverIsReady =300serverCondition.await(90L, TimeUnit.SECONDS);301if (!serverIsReady) {302System.out.println(303"The server is not ready yet in 90 seconds. " +304"Ignore in client side.");305return;306}307308if (isCustomizedClientConnection()) {309// Signal the server, the client is ready to communicate.310clientCondition.countDown();311312// Run the application in client side.313runClientApplication(serverPort);314315return;316}317318SSLContext context = createClientSSLContext();319SSLSocketFactory sslsf = context.getSocketFactory();320321try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket()) {322try {323configureClientSocket(sslSocket);324sslSocket.connect(325new InetSocketAddress("localhost", serverPort), 15000);326} catch (IOException ioe) {327// The server side may be impacted by naughty test cases or328// third party routines, and cannot accept connections.329//330// Just ignore the test if the connection cannot be331// established.332System.out.println(333"Cannot make a connection in 15 seconds. " +334"Ignore in client side.");335return;336}337338// OK, here the client and server get connected.339340// Signal the server, the client is ready to communicate.341clientCondition.countDown();342343// There is still a chance in theory that the server thread may344// wait client-ready timeout and then quit. The chance should345// be really rare so we don't consider it until it becomes a346// real problem.347348// Run the application in client side.349runClientApplication(sslSocket);350}351}352353/*354* =============================================355* Stuffs to customize the SSLContext instances.356*/357358/*359* =======================================360* Certificates and keys used in the test.361*/362// Trusted certificates.363private final static String[] trustedCertStrs = {364// SHA256withECDSA, curve prime256v1365// Validity366// Not Before: May 22 07:18:16 2018 GMT367// Not After : May 17 07:18:16 2038 GMT368// Subject Key Identifier:369// 60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86370"-----BEGIN CERTIFICATE-----\n" +371"MIIBvjCCAWOgAwIBAgIJAIvFG6GbTroCMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" +372"AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +373"ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMDsxCzAJBgNVBAYTAlVT\n" +374"MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTBZ\n" +375"MBMGByqGSM49AgEGCCqGSM49AwEHA0IABBz1WeVb6gM2mh85z3QlvaB/l11b5h0v\n" +376"LIzmkC3DKlVukZT+ltH2Eq1oEkpXuf7QmbM0ibrUgtjsWH3mULfmcWmjUDBOMB0G\n" +377"A1UdDgQWBBRgz71z//oaMNKk7NNJcUbvGjWghjAfBgNVHSMEGDAWgBRgz71z//oa\n" +378"MNKk7NNJcUbvGjWghjAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQCG\n" +379"6wluh1r2/T6L31mZXRKf9JxeSf9pIzoLj+8xQeUChQIhAJ09wAi1kV8yePLh2FD9\n" +380"2YEHlSQUAbwwqCDEVB5KxaqP\n" +381"-----END CERTIFICATE-----",382// -----BEGIN PRIVATE KEY-----383// MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg/HcHdoLJCdq3haVd384// XZTSKP00YzM3xX97l98vGL/RI1KhRANCAAQc9VnlW+oDNpofOc90Jb2gf5ddW+Yd385// LyyM5pAtwypVbpGU/pbR9hKtaBJKV7n+0JmzNIm61ILY7Fh95lC35nFp386// -----END PRIVATE KEY-----387388// SHA256withRSA, 2048 bits389// Validity390// Not Before: May 22 07:18:16 2018 GMT391// Not After : May 17 07:18:16 2038 GMT392// Subject Key Identifier:393// 0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C394"-----BEGIN CERTIFICATE-----\n" +395"MIIDSTCCAjGgAwIBAgIJAI4ZF3iy8zG+MA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" +396"BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" +397"aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMDsxCzAJBgNVBAYT\n" +398"AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +399"ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALpMcY7aWieXDEM1/YJf\n" +400"JW27b4nRIFZyEYhEloyGsKTuQiiQjc8cqRZFNXe2vwziDB4IyTEl0Hjl5QF6ZaQE\n" +401"huPzzwvQm1pv64KrRXrmj3FisQK8B5OWLty9xp6xDqsaMRoyObLK+oIb20T5fSlE\n" +402"evmo1vYjnh8CX0Yzx5Gr5ye6YSEHQvYOWEws8ad17OlyToR2KMeC8w4qo6rs59pW\n" +403"g7Mxn9vo22ImDzrtAbTbXbCias3xlE0Bp0h5luyf+5U4UgksoL9B9r2oP4GrLNEV\n" +404"oJk57t8lwaR0upiv3CnS8LcJELpegZub5ggqLY8ZPYFQPjlK6IzLOm6rXPgZiZ3m\n" +405"RL0CAwEAAaNQME4wHQYDVR0OBBYEFA3dk8n+S701t+iZeJD721o92xVMMB8GA1Ud\n" +406"IwQYMBaAFA3dk8n+S701t+iZeJD721o92xVMMAwGA1UdEwQFMAMBAf8wDQYJKoZI\n" +407"hvcNAQELBQADggEBAJTRC3rKUUhVH07/1+stUungSYgpM08dY4utJq0BDk36BbmO\n" +408"0AnLDMbkwFdHEoqF6hQIfpm7SQTmXk0Fss6Eejm8ynYr6+EXiRAsaXOGOBCzF918\n" +409"/RuKOzqABfgSU4UBKECLM5bMfQTL60qx+HdbdVIpnikHZOFfmjCDVxoHsGyXc1LW\n" +410"Jhkht8IGOgc4PMGvyzTtRFjz01kvrVQZ75aN2E0GQv6dCxaEY0i3ypSzjUWAKqDh\n" +411"3e2OLwUSvumcdaxyCdZAOUsN6pDBQ+8VRG7KxnlRlY1SMEk46QgQYLbPDe/+W/yH\n" +412"ca4PejicPeh+9xRAwoTpiE2gulfT7Lm+fVM7Ruc=\n" +413"-----END CERTIFICATE-----",414// -----BEGIN PRIVATE KEY-----415// MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC6THGO2lonlwxD416// Nf2CXyVtu2+J0SBWchGIRJaMhrCk7kIokI3PHKkWRTV3tr8M4gweCMkxJdB45eUB417// emWkBIbj888L0Jtab+uCq0V65o9xYrECvAeTli7cvcaesQ6rGjEaMjmyyvqCG9tE418// +X0pRHr5qNb2I54fAl9GM8eRq+cnumEhB0L2DlhMLPGndezpck6EdijHgvMOKqOq419// 7OfaVoOzMZ/b6NtiJg867QG0212womrN8ZRNAadIeZbsn/uVOFIJLKC/Qfa9qD+B420// qyzRFaCZOe7fJcGkdLqYr9wp0vC3CRC6XoGbm+YIKi2PGT2BUD45SuiMyzpuq1z4421// GYmd5kS9AgMBAAECggEAFHSoU2MuWwJ+2jJnb5U66t2V1bAcuOE1g5zkWvG/G5z9422// rq6Qo5kmB8f5ovdx6tw3MGUOklLwnRXBG3RxDJ1iokz3AvkY1clMNsDPlDsUrQKF423// JSO4QUBQTPSZhnsyfR8XHSU+qJ8Y+ohMfzpVv95BEoCzebtXdVgxVegBlcEmVHo2424// kMmkRN+bYNsr8eb2r+b0EpyumS39ZgKYh09+cFb78y3T6IFMGcVJTP6nlGBFkmA/425// 25pYeCF2tSki08qtMJZQAvKfw0Kviibk7ZxRbJqmc7B1yfnOEHP6ftjuvKl2+RP/426// +5P5f8CfIP6gtA0LwSzAqQX/hfIKrGV5j0pCqrD0kQKBgQDeNR6Xi4sXVq79lihO427// a1bSeV7r8yoQrS8x951uO+ox+UIZ1MsAULadl7zB/P0er92p198I9M/0Jth3KBuS428// zj45mucvpiiGvmQlMKMEfNq4nN7WHOu55kufPswQB2mR4J3xmwI+4fM/nl1zc82h429// De8JSazRldJXNhfx0RGFPmgzbwKBgQDWoVXrXLbCAn41oVnWB8vwY9wjt92ztDqJ430// HMFA/SUohjePep9UDq6ooHyAf/Lz6oE5NgeVpPfTDkgvrCFVKnaWdwALbYoKXT2W431// 9FlyJox6eQzrtHAacj3HJooXWuXlphKSizntfxj3LtMR9BmrmRJOfK+SxNOVJzW2432// +MowT20EkwKBgHmpB8jdZBgxI7o//m2BI5Y1UZ1KE5vx1kc7VXzHXSBjYqeV9FeF433// 2ZZLP9POWh/1Fh4pzTmwIDODGT2UPhSQy0zq3O0fwkyT7WzXRknsuiwd53u/dejg434// iEL2NPAJvulZ2+AuiHo5Z99LK8tMeidV46xoJDDUIMgTG+UQHNGhK5gNAoGAZn/S435// Cn7SgMC0CWSvBHnguULXZO9wH1wZAFYNLL44OqwuaIUFBh2k578M9kkke7woTmwx436// HxQTjmWpr6qimIuY6q6WBN8hJ2Xz/d1fwhYKzIp20zHuv5KDUlJjbFfqpsuy3u1C437// kts5zwI7pr1ObRbDGVyOdKcu7HI3QtR5qqyjwaUCgYABo7Wq6oHva/9V34+G3Goh438// 63bYGUnRw2l5BD11yhQv8XzGGZFqZVincD8gltNThB0Dc/BI+qu3ky4YdgdZJZ7K439// z51GQGtaHEbrHS5caV79yQ8QGY5mUVH3E+VXSxuIqb6pZq2DH4sTAEFHyncddmOH440// zoXBInYwRG9KE/Bw5elhUw==441// -----END PRIVATE KEY-----442443// SHA256withDSA, 2048 bits444// Validity445// Not Before: May 22 07:18:18 2018 GMT446// Not After : May 17 07:18:18 2038 GMT447// Subject Key Identifier:448// 76:66:9E:F7:3B:DD:45:E5:3B:D9:72:3C:3F:F0:54:39:86:31:26:53449"-----BEGIN CERTIFICATE-----\n" +450"MIIErjCCBFSgAwIBAgIJAOktYLNCbr02MAsGCWCGSAFlAwQDAjA7MQswCQYDVQQG\n" +451"EwJVUzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2\n" +452"Y2UwHhcNMTgwNTIyMDcxODE4WhcNMzgwNTE3MDcxODE4WjA7MQswCQYDVQQGEwJV\n" +453"UzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2Y2Uw\n" +454"ggNHMIICOQYHKoZIzjgEATCCAiwCggEBAO5GyPhSm0ze3LSu+gicdULLj05iOfTL\n" +455"UvZQ29sYz41zmqrLBQbdKiHqgJu2Re9sgTb5suLNjF047TOLPnU3jhPtWm2X8Xzi\n" +456"VGIcHym/Q/MeZxStt/88seqroI3WOKzIML2GcrishT+lcGrtH36Tf1+ue2Snn3PS\n" +457"WyxygNqPjllP5uUjYmFLvAf4QLMldkd/D2VxcwsHjB8y5iUZsXezc/LEhRZS/02m\n" +458"ivqlRw3AMkq/OVe/ZtxFWsP0nsfxEGdZuaUFpppGfixxFvymrB3+J51cTt+pZBDq\n" +459"D2y0DYfc+88iCs4jwHTfcDIpLb538HBjBj2rEgtQESQmB0ooD/+wsPsCIQC1bYch\n" +460"gElNtDYL3FgpLgNSUYp7gIWv9ehaC7LO2z7biQKCAQBitvFOnDkUja8NAF7lDpOV\n" +461"b5ipQ8SicBLW3kQamxhyuyxgZyy/PojZ/oPorkqW/T/A0rhnG6MssEpAtdiwVB+c\n" +462"rBYGo3bcwmExJhdOJ6dYuKFppPWhCwKMHs9npK+lqBMl8l5j58xlcFeC7ZfGf8GY\n" +463"GkhFW0c44vEQhMMbac6ZTTP4mw+1t7xJfmDMlLEyIpTXaAAk8uoVLWzQWnR40sHi\n" +464"ybvS0u3JxQkb7/y8tOOZu8qlz/YOS7lQ6UxUGX27Ce1E0+agfPphetoRAlS1cezq\n" +465"Wa7r64Ga0nkj1kwkcRqjgTiJx0NwnUXr78VAXFhVF95+O3lfqhvdtEGtkhDGPg7N\n" +466"A4IBBgACggEBAMmSHQK0w2i+iqUjOPzn0yNEZrzepLlLeQ1tqtn0xnlv5vBAeefD\n" +467"Pm9dd3tZOjufVWP7hhEz8xPobb1CS4e3vuQiv5UBfhdPL3f3l9T7JMAKPH6C9Vve\n" +468"OQXE5eGqbjsySbcmseHoYUt1WCSnSda1opX8zchX04e7DhGfE2/L9flpYEoSt8lI\n" +469"vMNjgOwvKdW3yvPt1/eBBHYNFG5gWPv/Q5KoyCtHS03uqGm4rNc/wZTIEEfd66C+\n" +470"QRaUltjOaHmtwOdDHaNqwhYZSVOip+Mo+TfyzHFREcdHLapo7ZXqbdYkRGxRR3d+\n" +471"3DfHaraJO0OKoYlPkr3JMvM/MSGR9AnZOcejUDBOMB0GA1UdDgQWBBR2Zp73O91F\n" +472"5TvZcjw/8FQ5hjEmUzAfBgNVHSMEGDAWgBR2Zp73O91F5TvZcjw/8FQ5hjEmUzAM\n" +473"BgNVHRMEBTADAQH/MAsGCWCGSAFlAwQDAgNHADBEAiBzriYE41M2y9Hy5ppkL0Qn\n" +474"dIlNc8JhXT/PHW7GDtViagIgMko8Qoj9gDGPK3+O9E8DC3wGiiF9CObM4LN387ok\n" +475"J+g=\n" +476"-----END CERTIFICATE-----"477// -----BEGIN PRIVATE KEY-----478// MIICZQIBADCCAjkGByqGSM44BAEwggIsAoIBAQDuRsj4UptM3ty0rvoInHVCy49O479// Yjn0y1L2UNvbGM+Nc5qqywUG3Soh6oCbtkXvbIE2+bLizYxdOO0ziz51N44T7Vpt480// l/F84lRiHB8pv0PzHmcUrbf/PLHqq6CN1jisyDC9hnK4rIU/pXBq7R9+k39frntk481// p59z0lsscoDaj45ZT+blI2JhS7wH+ECzJXZHfw9lcXMLB4wfMuYlGbF3s3PyxIUW482// Uv9Npor6pUcNwDJKvzlXv2bcRVrD9J7H8RBnWbmlBaaaRn4scRb8pqwd/iedXE7f483// qWQQ6g9stA2H3PvPIgrOI8B033AyKS2+d/BwYwY9qxILUBEkJgdKKA//sLD7AiEA484// tW2HIYBJTbQ2C9xYKS4DUlGKe4CFr/XoWguyzts+24kCggEAYrbxTpw5FI2vDQBe485// 5Q6TlW+YqUPEonAS1t5EGpsYcrssYGcsvz6I2f6D6K5Klv0/wNK4ZxujLLBKQLXY486// sFQfnKwWBqN23MJhMSYXTienWLihaaT1oQsCjB7PZ6SvpagTJfJeY+fMZXBXgu2X487// xn/BmBpIRVtHOOLxEITDG2nOmU0z+JsPtbe8SX5gzJSxMiKU12gAJPLqFS1s0Fp0488// eNLB4sm70tLtycUJG+/8vLTjmbvKpc/2Dku5UOlMVBl9uwntRNPmoHz6YXraEQJU489// tXHs6lmu6+uBmtJ5I9ZMJHEao4E4icdDcJ1F6+/FQFxYVRfefjt5X6ob3bRBrZIQ490// xj4OzQQjAiEAsceWOM8do4etxp2zgnoNXV8PUUyqWhz1+0srcKV7FR4=491// -----END PRIVATE KEY-----492};493494// End entity certificate.495private final static String[] endEntityCertStrs = {496// SHA256withECDSA, curve prime256v1497// Validity498// Not Before: May 22 07:18:16 2018 GMT499// Not After : May 17 07:18:16 2038 GMT500// Authority Key Identifier:501// 60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86502"-----BEGIN CERTIFICATE-----\n" +503"MIIBqjCCAVCgAwIBAgIJAPLY8qZjgNRAMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" +504"AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +505"ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMFUxCzAJBgNVBAYTAlVT\n" +506"MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTEY\n" +507"MBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\n" +508"QgAEb+9n05qfXnfHUb0xtQJNS4JeSi6IjOfW5NqchvKnfJey9VkJzR7QHLuOESdf\n" +509"xlR7q8YIWgih3iWLGfB+wxHiOqMjMCEwHwYDVR0jBBgwFoAUYM+9c//6GjDSpOzT\n" +510"SXFG7xo1oIYwCgYIKoZIzj0EAwIDSAAwRQIgWpRegWXMheiD3qFdd8kMdrkLxRbq\n" +511"1zj8nQMEwFTUjjQCIQDRIrAjZX+YXHN9b0SoWWLPUq0HmiFIi8RwMnO//wJIGQ==\n" +512"-----END CERTIFICATE-----",513514// SHA256withRSA, 2048 bits515// Validity516// Not Before: May 22 07:18:16 2018 GMT517// Not After : May 17 07:18:16 2038 GMT518// Authority Key Identifier:519// 0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C520"-----BEGIN CERTIFICATE-----\n" +521"MIIDNjCCAh6gAwIBAgIJAO2+yPcFryUTMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" +522"BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" +523"aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMFUxCzAJBgNVBAYT\n" +524"AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +525"ZTEYMBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOC\n" +526"AQ8AMIIBCgKCAQEAszfBobWfZIp8AgC6PiWDDavP65mSvgCXUGxACbxVNAfkLhNR\n" +527"QOsHriRB3X1Q3nvO9PetC6wKlvE9jlnDDj7D+1j1r1CHO7ms1fq8rfcQYdkanDtu\n" +528"4AlHo8v+SSWX16MIXFRYDj2VVHmyPtgbltcg4zGAuwT746FdLI94uXjJjq1IOr/v\n" +529"0VIlwE5ORWH5Xc+5Tj+oFWK0E4a4GHDgtKKhn2m72hN56/GkPKGkguP5NRS1qYYV\n" +530"/EFkdyQMOV8J1M7HaicSft4OL6eKjTrgo93+kHk+tv0Dc6cpVBnalX3TorG8QI6B\n" +531"cHj1XQd78oAlAC+/jF4pc0mwi0un49kdK9gRfQIDAQABoyMwITAfBgNVHSMEGDAW\n" +532"gBQN3ZPJ/ku9NbfomXiQ+9taPdsVTDANBgkqhkiG9w0BAQsFAAOCAQEApXS0nKwm\n" +533"Kp8gpmO2yG1rpd1+2wBABiMU4JZaTqmma24DQ3RzyS+V2TeRb29dl5oTUEm98uc0\n" +534"GPZvhK8z5RFr4YE17dc04nI/VaNDCw4y1NALXGs+AHkjoPjLyGbWpi1S+gfq2sNB\n" +535"Ekkjp6COb/cb9yiFXOGVls7UOIjnVZVd0r7KaPFjZhYh82/f4PA/A1SnIKd1+nfH\n" +536"2yk7mSJNC7Z3qIVDL8MM/jBVwiC3uNe5GPB2uwhd7k5LGAVN3j4HQQGB0Sz+VC1h\n" +537"92oi6xDa+YBva2fvHuCd8P50DDjxmp9CemC7rnZ5j8egj88w14X44Xjb/Fd/ApG9\n" +538"e57NnbT7KM+Grw==\n" +539"-----END CERTIFICATE-----",540541// SHA256withRSA, curv prime256v1542// Validity543// Not Before: May 22 07:18:16 2018 GMT544// Not After : May 21 07:18:16 2028 GMT545// Authority Key Identifier:546// 0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C547"-----BEGIN CERTIFICATE-----\n" +548"MIICazCCAVOgAwIBAgIJAO2+yPcFryUUMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" +549"BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" +550"aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0yODA1MjEwNzE4MTZaMFUxCzAJBgNVBAYT\n" +551"AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +552"ZTEYMBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0D\n" +553"AQcDQgAE59MERNTlVZ1eeps8Z3Oue5ZkgQdPtD+WIE6tj3PbIKpxGPDxvfNP959A\n" +554"yQjEK/ehWQVrCMmNoEkIzY+IIBgB06MjMCEwHwYDVR0jBBgwFoAUDd2Tyf5LvTW3\n" +555"6Jl4kPvbWj3bFUwwDQYJKoZIhvcNAQELBQADggEBAFOTVEqs70ykhZiIdrEsF1Ra\n" +556"I3B2rLvwXZk52uSltk2/bzVvewA577ZCoxQ1pL7ynkisPfBN1uVYtHjM1VA3RC+4\n" +557"+TAK78dnI7otYjWoHp5rvs4l6c/IbOspS290IlNuDUxMErEm5wxIwj+Aukx/1y68\n" +558"hOyCvHBLMY2c1LskH1MMBbDuS1aI+lnGpToi+MoYObxGcV458vxuT8+wwV8Fkpvd\n" +559"ll8IIFmeNPRv+1E+lXbES6CSNCVaZ/lFhPgdgYKleN7sfspiz50DG4dqafuEAaX5\n" +560"xaK1NWXJxTRz0ROH/IUziyuDW6jphrlgit4+3NCzp6vP9hAJQ8Vhcj0n15BKHIQ=\n" +561"-----END CERTIFICATE-----",562563// SHA256withDSA, 2048 bits564// Validity565// Not Before: May 22 07:18:20 2018 GMT566// Not After : May 17 07:18:20 2038 GMT567// Authority Key Identifier:568// 76:66:9E:F7:3B:DD:45:E5:3B:D9:72:3C:3F:F0:54:39:86:31:26:53569"-----BEGIN CERTIFICATE-----\n" +570"MIIEnDCCBEGgAwIBAgIJAP/jh1qVhNVjMAsGCWCGSAFlAwQDAjA7MQswCQYDVQQG\n" +571"EwJVUzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2\n" +572"Y2UwHhcNMTgwNTIyMDcxODIwWhcNMzgwNTE3MDcxODIwWjBVMQswCQYDVQQGEwJV\n" +573"UzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2Y2Ux\n" +574"GDAWBgNVBAMMD1JlZ3Jlc3Npb24gVGVzdDCCA0cwggI6BgcqhkjOOAQBMIICLQKC\n" +575"AQEAmlavgoJrMcjqWRVcDE2dmWAPREgnzQvneEDef68cprDzjSwvOs5QeFyx75ib\n" +576"ado1e6jO/rW1prCGWHDD1oA/Tn4Pk3vu0nUxzvl1qATc+aJbpUU5Op0bvp6LbCsQ\n" +577"QslV9FeRh7Eb7bP6gpc/kHCBzEgC1VCK7prccXWy+t6SMOHbND3h+UbckfSaUuaV\n" +578"sVJNTD1D6GElfRj4Nmz1BGPfSYvKorwNZEU3gXwFgtDoAcGx7tcyClLpDHfqRfw/\n" +579"7yiqLyeiP7D4hl5lMNouJWDlAdMFp0FMgS3s9VDFinIcr6VtBWMTG7+4+czHAB+3\n" +580"fvrwlqNzhBn3uFHrekN/w8fNxwIhAJo7Sae1za7IMW0Q6hE5B4b+s2B/FaKPoA4E\n" +581"jtZu13B9AoIBAQCOZqLMKfvqZWUgT0PQ3QjR7dAFdd06I9Y3+TOQzZk1+j+vw/6E\n" +582"X4vFItX4gihb/u5Q9CdmpwhVGi7bvo+7+/IKeTgoQ6f5+PSug7SrWWUQ5sPwaZui\n" +583"zXZJ5nTeZDucFc2yFx0wgnjbPwiUxZklOT7xGiOMtzOTa2koCz5KuIBL+/wPKKxm\n" +584"ypo9VoY9xfbdU6LMXZv/lpD5XTM9rYHr/vUTNkukvV6Hpm0YMEWhVZKUJiqCqTqG\n" +585"XHaleOxSw6uQWB/+TznifcC7gB48UOQjCqOKf5VuwQneJLhlhU/jhRV3xtr+hLZa\n" +586"hW1wYhVi8cjLDrZFKlgEQqhB4crnJU0mJY+tA4IBBQACggEAID0ezl00/X8mv7eb\n" +587"bzovum1+DEEP7FM57k6HZEG2N3ve4CW+0m9Cd+cWPz8wkZ+M0j/Eqa6F0IdbkXEc\n" +588"Q7CuzvUyJ57xQ3L/WCgXsiS+Bh8O4Mz7GwW22CGmHqafbVv+hKBfr8MkskO6GJUt\n" +589"SUF/CVLzB4gMIvZMH26tBP2xK+i7FeEK9kT+nGdzQSZBAhFYpEVCBplHZO24/OYq\n" +590"1DNoU327nUuXIhmsfA8N0PjiWbIZIjTPwBGr9H0LpATI7DIDNcvRRvtROP+pBU9y\n" +591"fuykPkptg9C0rCM9t06bukpOSaEz/2VIQdLE8fHYFA6pHZ6CIc2+5cfvMgTPhcjz\n" +592"W2jCt6MjMCEwHwYDVR0jBBgwFoAUdmae9zvdReU72XI8P/BUOYYxJlMwCwYJYIZI\n" +593"AWUDBAMCA0gAMEUCIQCeI5fN08b9BpOaHdc3zQNGjp24FOL/RxlBLeBAorswJgIg\n" +594"JEZ8DhYxQy1O7mmZ2UIT7op6epWMB4dENjs0qWPmcKo=\n" +595"-----END CERTIFICATE-----"596};597598// Private key in the format of PKCS#8.599private final static String[] endEntityPrivateKeys = {600//601// EC private key related to cert endEntityCertStrs[0].602//603"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgn5K03bpTLjEtFQRa\n" +604"JUtx22gtmGEvvSUSQdimhGthdtihRANCAARv72fTmp9ed8dRvTG1Ak1Lgl5KLoiM\n" +605"59bk2pyG8qd8l7L1WQnNHtAcu44RJ1/GVHurxghaCKHeJYsZ8H7DEeI6",606607//608// RSA private key related to cert endEntityCertStrs[1].609//610"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzN8GhtZ9kinwC\n" +611"ALo+JYMNq8/rmZK+AJdQbEAJvFU0B+QuE1FA6weuJEHdfVDee870960LrAqW8T2O\n" +612"WcMOPsP7WPWvUIc7uazV+ryt9xBh2RqcO27gCUejy/5JJZfXowhcVFgOPZVUebI+\n" +613"2BuW1yDjMYC7BPvjoV0sj3i5eMmOrUg6v+/RUiXATk5FYfldz7lOP6gVYrQThrgY\n" +614"cOC0oqGfabvaE3nr8aQ8oaSC4/k1FLWphhX8QWR3JAw5XwnUzsdqJxJ+3g4vp4qN\n" +615"OuCj3f6QeT62/QNzpylUGdqVfdOisbxAjoFwePVdB3vygCUAL7+MXilzSbCLS6fj\n" +616"2R0r2BF9AgMBAAECggEASIkPkMCuw4WdTT44IwERus3IOIYOs2IP3BgEDyyvm4B6\n" +617"JP/iihDWKfA4zEl1Gqcni1RXMHswSglXra682J4kui02Ov+vzEeJIY37Ibn2YnP5\n" +618"ZjRT2s9GtI/S2o4hl8A/mQb2IMViFC+xKehTukhV4j5d6NPKk0XzLR7gcMjnYxwn\n" +619"l21fS6D2oM1xRG/di7sL+uLF8EXLRzfiWDNi12uQv4nwtxPKvuKhH6yzHt7YqMH0\n" +620"46pmDKDaxV4w1JdycjCb6NrCJOYZygoQobuZqOQ30UZoZsPJrtovkncFr1e+lNcO\n" +621"+aWDfOLCtTH046dEQh5oCShyXMybNlry/QHsOtHOwQKBgQDh2iIjs+FPpQy7Z3EX\n" +622"DGEvHYqPjrYO9an2KSRr1m9gzRlWYxKY46WmPKwjMerYtra0GP+TBHrgxsfO8tD2\n" +623"wUAII6sd1qup0a/Sutgf2JxVilLykd0+Ge4/Cs51tCdJ8EqDV2B6WhTewOY2EGvg\n" +624"JiKYkeNwgRX/9M9CFSAMAk0hUQKBgQDLJAartL3DoGUPjYtpJnfgGM23yAGl6G5r\n" +625"NSXDn80BiYIC1p0bG3N0xm3yAjqOtJAUj9jZbvDNbCe3GJfLARMr23legX4tRrgZ\n" +626"nEdKnAFKAKL01oM+A5/lHdkwaZI9yyv+hgSVdYzUjB8rDmzeVQzo1BT7vXypt2yV\n" +627"6O1OnUpCbQKBgA/0rzDChopv6KRcvHqaX0tK1P0rYeVQqb9ATNhpf9jg5Idb3HZ8\n" +628"rrk91BNwdVz2G5ZBpdynFl9G69rNAMJOCM4KZw5mmh4XOEq09Ivba8AHU7DbaTv3\n" +629"7QL7KnbaUWRB26HHzIMYVh0el6T+KADf8NXCiMTr+bfpfbL3dxoiF3zhAoGAbCJD\n" +630"Qse1dBs/cKYCHfkSOsI5T6kx52Tw0jS6Y4X/FOBjyqr/elyEexbdk8PH9Ar931Qr\n" +631"NKMvn8oA4iA/PRrXX7M2yi3YQrWwbkGYWYjtzrzEAdzmg+5eARKAeJrZ8/bg9l3U\n" +632"ttKaItJsDPlizn8rngy3FsJpR9aSAMK6/+wOiYkCgYEA1tZkI1rD1W9NYZtbI9BE\n" +633"qlJVFi2PBOJMKNuWdouPX3HLQ72GJSQff2BFzLTELjweVVJ0SvY4IipzpQOHQOBy\n" +634"5qh/p6izXJZh3IHtvwVBjHoEVplg1b2+I5e3jDCfqnwcQw82dW5SxOJMg1h/BD0I\n" +635"qAL3go42DYeYhu/WnECMeis=",636637//638// EC private key related to cert endEntityCertStrs[2].639//640"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgGVc7hICpmp91jbYe\n" +641"nrr8nYHD37RZP3VENY+szuA7WjuhRANCAATn0wRE1OVVnV56mzxnc657lmSBB0+0\n" +642"P5YgTq2Pc9sgqnEY8PG980/3n0DJCMQr96FZBWsIyY2gSQjNj4ggGAHT",643644//645// DSA private key related to cert endEntityCertStrs[3].646//647"MIICZQIBADCCAjoGByqGSM44BAEwggItAoIBAQCaVq+CgmsxyOpZFVwMTZ2ZYA9E\n" +648"SCfNC+d4QN5/rxymsPONLC86zlB4XLHvmJtp2jV7qM7+tbWmsIZYcMPWgD9Ofg+T\n" +649"e+7SdTHO+XWoBNz5olulRTk6nRu+notsKxBCyVX0V5GHsRvts/qClz+QcIHMSALV\n" +650"UIrumtxxdbL63pIw4ds0PeH5RtyR9JpS5pWxUk1MPUPoYSV9GPg2bPUEY99Ji8qi\n" +651"vA1kRTeBfAWC0OgBwbHu1zIKUukMd+pF/D/vKKovJ6I/sPiGXmUw2i4lYOUB0wWn\n" +652"QUyBLez1UMWKchyvpW0FYxMbv7j5zMcAH7d++vCWo3OEGfe4Uet6Q3/Dx83HAiEA\n" +653"mjtJp7XNrsgxbRDqETkHhv6zYH8Voo+gDgSO1m7XcH0CggEBAI5moswp++plZSBP\n" +654"Q9DdCNHt0AV13Toj1jf5M5DNmTX6P6/D/oRfi8Ui1fiCKFv+7lD0J2anCFUaLtu+\n" +655"j7v78gp5OChDp/n49K6DtKtZZRDmw/Bpm6LNdknmdN5kO5wVzbIXHTCCeNs/CJTF\n" +656"mSU5PvEaI4y3M5NraSgLPkq4gEv7/A8orGbKmj1Whj3F9t1Tosxdm/+WkPldMz2t\n" +657"gev+9RM2S6S9XoembRgwRaFVkpQmKoKpOoZcdqV47FLDq5BYH/5POeJ9wLuAHjxQ\n" +658"5CMKo4p/lW7BCd4kuGWFT+OFFXfG2v6EtlqFbXBiFWLxyMsOtkUqWARCqEHhyucl\n" +659"TSYlj60EIgIgLfA75+8KcKxdN8mr6gzGjQe7jPFGG42Ejhd7Q2F4wuw="660};661662// Private key algorithm of endEntityPrivateKeys.663private final static String[] endEntityPrivateKeyAlgs = {664"EC",665"RSA",666"EC",667"DSA",668};669670// Private key names of endEntityPrivateKeys.671private final static String[] endEntityPrivateKeyNames = {672"ecdsa",673"rsa",674"ec-rsa",675"dsa",676};677678/*679* Create an instance of SSLContext with the specified trust/key materials.680*/681private SSLContext createSSLContext(682String[] trustedMaterials,683String[] keyMaterialCerts,684String[] keyMaterialKeys,685String[] keyMaterialKeyAlgs,686String[] keyMaterialKeyNames,687ContextParameters params) throws Exception {688689KeyStore ts = null; // trust store690KeyStore ks = null; // key store691char passphrase[] = "passphrase".toCharArray();692693// Generate certificate from cert string.694CertificateFactory cf = CertificateFactory.getInstance("X.509");695696// Import the trused certs.697ByteArrayInputStream is;698if (trustedMaterials != null && trustedMaterials.length != 0) {699ts = KeyStore.getInstance("JKS");700ts.load(null, null);701702Certificate[] trustedCert =703new Certificate[trustedMaterials.length];704for (int i = 0; i < trustedMaterials.length; i++) {705String trustedCertStr = trustedMaterials[i];706707is = new ByteArrayInputStream(trustedCertStr.getBytes());708try {709trustedCert[i] = cf.generateCertificate(is);710} finally {711is.close();712}713714ts.setCertificateEntry("trusted-cert-" + i, trustedCert[i]);715}716}717718// Import the key materials.719//720// Note that certification pathes bigger than one are not supported yet.721boolean hasKeyMaterials =722(keyMaterialCerts != null) && (keyMaterialCerts.length != 0) &&723(keyMaterialKeys != null) && (keyMaterialKeys.length != 0) &&724(keyMaterialKeyAlgs != null) && (keyMaterialKeyAlgs.length != 0) &&725(keyMaterialCerts.length == keyMaterialKeys.length) &&726(keyMaterialCerts.length == keyMaterialKeyAlgs.length);727if (hasKeyMaterials) {728ks = KeyStore.getInstance("JKS");729ks.load(null, null);730731for (int i = 0; i < keyMaterialCerts.length; i++) {732String keyCertStr = keyMaterialCerts[i];733734// generate the private key.735PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(736Base64.getMimeDecoder().decode(keyMaterialKeys[i]));737KeyFactory kf =738KeyFactory.getInstance(keyMaterialKeyAlgs[i]);739PrivateKey priKey = kf.generatePrivate(priKeySpec);740741// generate certificate chain742is = new ByteArrayInputStream(keyCertStr.getBytes());743Certificate keyCert = null;744try {745keyCert = cf.generateCertificate(is);746} finally {747is.close();748}749750Certificate[] chain = new Certificate[] { keyCert };751752// import the key entry.753ks.setKeyEntry("cert-" + keyMaterialKeyNames[i],754priKey, passphrase, chain);755}756}757758// Create an SSLContext object.759TrustManagerFactory tmf =760TrustManagerFactory.getInstance(params.tmAlgorithm);761tmf.init(ts);762763SSLContext context = SSLContext.getInstance(params.contextProtocol);764if (hasKeyMaterials && ks != null) {765KeyManagerFactory kmf =766KeyManagerFactory.getInstance(params.kmAlgorithm);767kmf.init(ks, passphrase);768769context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);770} else {771context.init(null, tmf.getTrustManagers(), null);772}773774return context;775}776777/*778* =================================================779* Stuffs to boot up the client-server mode testing.780*/781private Thread clientThread = null;782private Thread serverThread = null;783private volatile Exception serverException = null;784private volatile Exception clientException = null;785786/*787* Should we run the client or server in a separate thread?788* Both sides can throw exceptions, but do you have a preference789* as to which side should be the main thread.790*/791private static final boolean separateServerThread = false;792793/*794* Boot up the testing, used to drive remainder of the test.795*/796private void bootup() throws Exception {797Exception startException = null;798try {799if (separateServerThread) {800startServer(true);801startClient(false);802} else {803startClient(true);804startServer(false);805}806} catch (Exception e) {807startException = e;808}809810/*811* Wait for other side to close down.812*/813if (separateServerThread) {814if (serverThread != null) {815serverThread.join();816}817} else {818if (clientThread != null) {819clientThread.join();820}821}822823/*824* When we get here, the test is pretty much over.825* Which side threw the error?826*/827Exception local;828Exception remote;829830if (separateServerThread) {831remote = serverException;832local = clientException;833} else {834remote = clientException;835local = serverException;836}837838Exception exception = null;839840/*841* Check various exception conditions.842*/843if ((local != null) && (remote != null)) {844// If both failed, return the curthread's exception.845local.initCause(remote);846exception = local;847} else if (local != null) {848exception = local;849} else if (remote != null) {850exception = remote;851} else if (startException != null) {852exception = startException;853}854855/*856* If there was an exception *AND* a startException,857* output it.858*/859if (exception != null) {860if (exception != startException && startException != null) {861exception.addSuppressed(startException);862}863throw exception;864}865866// Fall-through: no exception to throw!867}868869private void startServer(boolean newThread) throws Exception {870if (newThread) {871serverThread = new Thread() {872@Override873public void run() {874try {875doServerSide();876} catch (Exception e) {877/*878* Our server thread just died.879*880* Release the client, if not active already...881*/882logException("Server died", e);883serverException = e;884}885}886};887serverThread.start();888} else {889try {890doServerSide();891} catch (Exception e) {892logException("Server failed", e);893serverException = e;894}895}896}897898private void startClient(boolean newThread) throws Exception {899if (newThread) {900clientThread = new Thread() {901@Override902public void run() {903try {904doClientSide();905} catch (Exception e) {906/*907* Our client thread just died.908*/909logException("Client died", e);910clientException = e;911}912}913};914clientThread.start();915} else {916try {917doClientSide();918} catch (Exception e) {919logException("Client failed", e);920clientException = e;921}922}923}924925private synchronized void logException(String prefix, Throwable cause) {926System.out.println(prefix + ": " + cause);927cause.printStackTrace(System.out);928}929}930931932