From 1b13083defbde2dae2baf535eeae272c7c9e1ab0 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Tue, 19 Oct 2010 17:20:57 +0000 Subject: [PATCH] THRIFT-106. java: TSSLServerSocket This patch adds support for SSL-encrypted client and server sockets. Patch: Nirmal Ranganathan git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@1024328 13f79535-47bb-0310-9956-ffa450edef68 --- lib/java/build.xml | 4 + .../transport/TSSLTransportFactory.java | 332 ++++++++++++++++++ .../thrift/transport/TServerSocket.java | 3 + lib/java/test/.keystore | Bin 0 -> 1414 bytes lib/java/test/.truststore | Bin 0 -> 708 bytes .../apache/thrift/server/ServerTestBase.java | 12 +- .../transport/TestTSSLTransportFactory.java | 81 +++++ tutorial/java/JavaClient | 2 +- tutorial/java/JavaServer | 7 + tutorial/java/src/JavaClient.java | 101 +++--- tutorial/java/src/JavaServer.java | 108 ++++-- 11 files changed, 579 insertions(+), 71 deletions(-) create mode 100644 lib/java/src/org/apache/thrift/transport/TSSLTransportFactory.java create mode 100644 lib/java/test/.keystore create mode 100644 lib/java/test/.truststore create mode 100644 lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactory.java diff --git a/lib/java/build.xml b/lib/java/build.xml index 4975068b..a80f749c 100644 --- a/lib/java/build.xml +++ b/lib/java/build.xml @@ -195,6 +195,10 @@ > + + + + diff --git a/lib/java/src/org/apache/thrift/transport/TSSLTransportFactory.java b/lib/java/src/org/apache/thrift/transport/TSSLTransportFactory.java new file mode 100644 index 00000000..1e1c4c99 --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/TSSLTransportFactory.java @@ -0,0 +1,332 @@ +/* + * 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.thrift.transport; + +import java.io.FileInputStream; +import java.net.InetAddress; +import java.security.KeyStore; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManagerFactory; + +/** + * A Factory for providing and setting up Client and Server SSL wrapped + * TSocket and TServerSocket + */ +public class TSSLTransportFactory { + + /** + * Get a SSL wrapped TServerSocket bound to the specified port. In this + * configuration the default settings are used. Default settings are retrieved + * from System properties that are set. + * + * Example system properties: + * -Djavax.net.ssl.trustStore= + * -Djavax.net.ssl.trustStorePassword=password + * -Djavax.net.ssl.keyStore= + * -Djavax.net.ssl.keyStorePassword=password + * + * @param port + * @return A SSL wrapped TServerSocket + * @throws TTransportException + */ + public static TServerSocket getServerSocket(int port) throws TTransportException { + return getServerSocket(port, 0); + } + + /** + * Get a default SSL wrapped TServerSocket bound to the specified port + * + * @param port + * @param clientTimeout + * @return A SSL wrapped TServerSocket + * @throws TTransportException + */ + public static TServerSocket getServerSocket(int port, int clientTimeout) throws TTransportException { + return getServerSocket(port, clientTimeout, false, null); + } + + /** + * Get a default SSL wrapped TServerSocket bound to the specified port and interface + * + * @param port + * @param clientTimeout + * @param ifAddress + * @return A SSL wrapped TServerSocket + * @throws TTransportException + */ + public static TServerSocket getServerSocket(int port, int clientTimeout, boolean clientAuth, InetAddress ifAddress) throws TTransportException { + SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); + return createServer(factory, port, clientTimeout, clientAuth, ifAddress, null); + } + + /** + * Get a configured SSL wrapped TServerSocket bound to the specified port and interface. + * Here the TSSLTransportParameters are used to set the values for the algorithms, keystore, + * truststore and other settings + * + * @param port + * @param clientTimeout + * @param ifAddress + * @param params + * @return A SSL wrapped TServerSocket + * @throws TTransportException + */ + public static TServerSocket getServerSocket(int port, int clientTimeout, InetAddress ifAddress, TSSLTransportParameters params) throws TTransportException { + if (params == null || !(params.isKeyStoreSet || params.isTrustStoreSet)) { + throw new TTransportException("Either one of the KeyStore or TrustStore must be set for SSLTransportParameters"); + } + + SSLContext ctx = createSSLContext(params); + return createServer(ctx.getServerSocketFactory(), port, clientTimeout, params.clientAuth, ifAddress, params); + } + + private static TServerSocket createServer(SSLServerSocketFactory factory, int port, int timeout, boolean clientAuth, + InetAddress ifAddress, TSSLTransportParameters params) throws TTransportException { + try { + SSLServerSocket serverSocket = (SSLServerSocket) factory.createServerSocket(port, 100, ifAddress); + serverSocket.setSoTimeout(timeout); + serverSocket.setNeedClientAuth(clientAuth); + if (params != null && params.cipherSuites != null) { + serverSocket.setEnabledCipherSuites(params.cipherSuites); + } + return new TServerSocket(serverSocket); + } catch (Exception e) { + throw new TTransportException("Could not bind to port " + port, e); + } + } + + /** + * Get a default SSL wrapped TSocket connected to the specified host and port. All + * the client methods return a bound connection. So there is no need to call open() on the + * TTransport. + * + * @param host + * @param port + * @param timeout + * @return A SSL wrapped TSocket + * @throws TTransportException + */ + public static TSocket getClientSocket(String host, int port, int timeout) throws TTransportException { + SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); + return createClient(factory, host, port, timeout); + } + + /** + * Get a default SSL wrapped TSocket connected to the specified host and port. + * + * @param host + * @param port + * @return A SSL wrapped TSocket + * @throws TTransportException + */ + public static TSocket getClientSocket(String host, int port) throws TTransportException { + return getClientSocket(host, port, 0); + } + + /** + * Get a custom configured SSL wrapped TSocket. The SSL settings are obtained from the + * passed in TSSLTransportParameters. + * + * @param host + * @param port + * @param timeout + * @param params + * @return A SSL wrapped TSocket + * @throws TTransportException + */ + public static TSocket getClientSocket(String host, int port, int timeout, TSSLTransportParameters params) throws TTransportException { + if (params == null || !(params.isKeyStoreSet || params.isTrustStoreSet)) { + throw new TTransportException("Either one of the KeyStore or TrustStore must be set for SSLTransportParameters"); + } + + SSLContext ctx = createSSLContext(params); + return createClient(ctx.getSocketFactory(), host, port, timeout); + } + + private static SSLContext createSSLContext(TSSLTransportParameters params) throws TTransportException { + SSLContext ctx; + try { + ctx = SSLContext.getInstance(params.protocol); + TrustManagerFactory tmf = null; + KeyManagerFactory kmf = null; + + if (params.isTrustStoreSet) { + tmf = TrustManagerFactory.getInstance(params.trustManagerType); + KeyStore ts = KeyStore.getInstance(params.trustStoreType); + ts.load(new FileInputStream(params.trustStore), params.trustPass.toCharArray()); + tmf.init(ts); + } + + if (params.isKeyStoreSet) { + kmf = KeyManagerFactory.getInstance(params.keyManagerType); + KeyStore ks = KeyStore.getInstance(params.keyStoreType); + ks.load(new FileInputStream(params.keyStore), params.keyPass.toCharArray()); + kmf.init(ks, params.keyPass.toCharArray()); + } + + if (params.isKeyStoreSet && params.isTrustStoreSet) { + ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + } + else if (params.isKeyStoreSet) { + ctx.init(kmf.getKeyManagers(), null, null); + } + else { + ctx.init(null, tmf.getTrustManagers(), null); + } + + } catch (Exception e) { + throw new TTransportException("Error creating the transport", e); + } + return ctx; + } + + private static TSocket createClient(SSLSocketFactory factory, String host, int port, int timeout) throws TTransportException { + try { + SSLSocket socket = (SSLSocket) factory.createSocket(host, port); + socket.setSoTimeout(timeout); + return new TSocket(socket); + } catch (Exception e) { + throw new TTransportException("Could not connect to " + host + " on port " + port, e); + } + } + + + /** + * A Class to hold all the SSL parameters + */ + public static class TSSLTransportParameters { + protected String protocol = "TLS"; + protected String keyStore; + protected String keyPass; + protected String keyManagerType = "SunX509"; + protected String keyStoreType = "JKS"; + protected String trustStore; + protected String trustPass; + protected String trustManagerType = "SunX509"; + protected String trustStoreType = "JKS"; + protected String[] cipherSuites; + protected boolean clientAuth = false; + protected boolean isKeyStoreSet = false; + protected boolean isTrustStoreSet = false; + + public TSSLTransportParameters() {} + + /** + * Create parameters specifying the protocol and cipher suites + * + * @param protocol The specific protocol (TLS/SSL) can be specified with versions + * @param cipherSuites + */ + public TSSLTransportParameters(String protocol, String[] cipherSuites) { + this(protocol, cipherSuites, false); + } + + /** + * Create parameters specifying the protocol, cipher suites and if client authentication + * is required + * + * @param protocol The specific protocol (TLS/SSL) can be specified with versions + * @param cipherSuites + * @param clientAuth + */ + public TSSLTransportParameters(String protocol, String[] cipherSuites, boolean clientAuth) { + if (protocol != null) { + this.protocol = protocol; + } + this.cipherSuites = cipherSuites; + this.clientAuth = clientAuth; + } + + /** + * Set the keystore, password, certificate type and the store type + * + * @param keyStore Location of the Keystore on disk + * @param keyPass Keystore password + * @param keyManagerType The default is X509 + * @param keyStoreType The default is JKS + */ + public void setKeyStore(String keyStore, String keyPass, String keyManagerType, String keyStoreType) { + this.keyStore = keyStore; + this.keyPass = keyPass; + if (keyManagerType != null) { + this.keyManagerType = keyManagerType; + } + if (keyStoreType != null) { + this.keyStoreType = keyStoreType; + } + isKeyStoreSet = true; + } + + /** + * Set the keystore and password + * + * @param keyStore Location of the Keystore on disk + * @param keyPass Keystore password + */ + public void setKeyStore(String keyStore, String keyPass) { + setKeyStore(keyStore, keyPass, null, null); + } + + /** + * Set the truststore, password, certificate type and the store type + * + * @param trustStore Location of the Truststore on disk + * @param trustPass Truststore password + * @param trustManagerType The default is X509 + * @param trustStoreType The default is JKS + */ + public void setTrustStore(String trustStore, String trustPass, String trustManagerType, String trustStoreType) { + this.trustStore = trustStore; + this.trustPass = trustPass; + if (trustManagerType != null) { + this.trustManagerType = trustManagerType; + } + if (trustStoreType != null) { + this.trustStoreType = trustStoreType; + } + isTrustStoreSet = true; + } + + /** + * Set the truststore and password + * + * @param trustStore Location of the Truststore on disk + * @param trustPass Truststore password + */ + public void setTrustStore(String trustStore, String trustPass) { + setTrustStore(trustStore, trustPass, null, null); + } + + /** + * Set if client authentication is required + * + * @param auth + */ + public void requireClientAuth(boolean clientAuth) { + this.clientAuth = clientAuth; + } + } +} diff --git a/lib/java/src/org/apache/thrift/transport/TServerSocket.java b/lib/java/src/org/apache/thrift/transport/TServerSocket.java index aae390df..9dad36d1 100644 --- a/lib/java/src/org/apache/thrift/transport/TServerSocket.java +++ b/lib/java/src/org/apache/thrift/transport/TServerSocket.java @@ -136,4 +136,7 @@ public class TServerSocket extends TServerTransport { close(); } + public ServerSocket getServerSocket() { + return serverSocket_; + } } diff --git a/lib/java/test/.keystore b/lib/java/test/.keystore new file mode 100644 index 0000000000000000000000000000000000000000..0c851114ff7d83c64f2371aa77c0a72c5e6b56de GIT binary patch literal 1414 zcmezO_TO6u1_mY|W&~rll8mCvv=Sg!yQjBA94NKRpowXl0UsNeHX9=gqZX4OBO@yV zOB2(gQ*V;XSC*S-zFcHiv|`sCuG&c(@BJ|^(06>YhG99&qQ;*;n>W@+SZqEi`-NA> zVFTM5)-M-1H-)C3y`8M}I*QNr3CoS;ExYBvF59D!7bDDgcYd>iPs?1E^06q+ zV!AnR$E%97iBHZdZRM;^x%vNR+z}zp`t?7jaJx#sm1K_O;+u1JZTbJF6*ode9|#JZ zu42qN<9F8g2HUP@moMoCPKce^>t--%*=a4k#2-uR!tXQ3epWHmkF(WPky zyE+vw-}<@2%=?b|BX9ZgWVIOwx0_`|ZYl_>70zI|q51E0_f8!TXRboNW~Fb%L8jI^ zOFd(^)O2$uNn10-{+%(WrNfUcI3-nbYQ^;r3kph4R_E&*)UK27b87gw%qsHP*#pHP z&p0MensTjKdaIk>`!z>)G=6tn^KwRGf?)E_o0lqeMCbhcczOM+36WeSE~YA5_Z|v3 z)&I3x@z19V3^~7&nWNmU9eC&+EpRqigL!@XC6OsTE~32AvPUKD8XLZM+U$F=PWf9( zQQX9I0a;%SnHguU?8vy4y>QBPzV|;4pY^f4&zF-`v*@@O-~A(sD)(mf`pzybO6!{B zX?B?DfJI}v_&PtI`LQkQ^%pA#F8F?L!It!7laHsCibki~=0$R}O}x^lIWc9!|9z*Z@KN1{7n{D!6iuvIwot+)wCNMu zX6wicW--4n9JYDTwyOJZ$(0+XYrh0{mg=uj3JrZGvtk~T3}=1w?*oNw4z=$mhZ_8> zI`Do^iNH_CH*s2TS8gl){ruO~Ns$NARtwo|l2@Pb|6T6%qp?Nc6wMl;XKG*xOvtUk zgxqM*#Q16fGZP~d6N}G!yNd?AY@Awc9&O)wfvK96!Jx6lPym?LnL}CFgxN#$vh(uG z^I#$z7$WQl5oH5KkS;D^DaV4u;QX|b^2DN41-Jatyp+U}%=|nFOcrP61t)=o_!MRm)GlG$~NL^xE!|M!VMe z1;5ja_`4wHTJG`uC>E<$JD)w%Ipeag=+3*Sv!eE3KCK3OqyInnk_ K5nP)B9|8cv8cNpy literal 0 HcmV?d00001 diff --git a/lib/java/test/.truststore b/lib/java/test/.truststore new file mode 100644 index 0000000000000000000000000000000000000000..c24b4a252a91b1e280e70de5ed787f358e1aebc4 GIT binary patch literal 708 zcmezO_TO6u1_mY|W(3o0B^gDTX(d3ec2B>!1_Nt^o~eN)P(`aj6H}u>6XUA|%uI|- zOe{X@?JgSdvT3^OEUBG48;sYK#I79d7+9zz)m&f2RZ{N z&MeFZ5ipPw=QT7iG%&C*G&MCbHIEYKH8L?UGc<#82a7Ws=Oc$7BP#=QV=piaJDD0A z8J2oqx_@BHk!kLy%wn>*v)5V7`W+E5BS>uZ@BY)5Esf(O%2qiwUA!6|d$MTDYpx5s z{+(g*s$&e#UU)A&Yu$$j5pqH^%AzjbQ8~Wko`u+RrL~b~ME~9VA{1UBnttr*-USDb zFJqi6Q26Tgw{<iyD>~hc^&V@6$y$rGX6Gu-yCL=> literal 0 HcmV?d00001 diff --git a/lib/java/test/org/apache/thrift/server/ServerTestBase.java b/lib/java/test/org/apache/thrift/server/ServerTestBase.java index 3bfc8d7e..95425203 100644 --- a/lib/java/test/org/apache/thrift/server/ServerTestBase.java +++ b/lib/java/test/org/apache/thrift/server/ServerTestBase.java @@ -367,7 +367,7 @@ public abstract class ServerTestBase extends TestCase { public void testIt() throws Exception { - for (TProtocolFactory protoFactory : PROTOCOLS) { + for (TProtocolFactory protoFactory : getProtocols()) { TestHandler handler = new TestHandler(); ThriftTest.Processor processor = new ThriftTest.Processor(handler); @@ -380,7 +380,7 @@ public abstract class ServerTestBase extends TestCase { TProtocol protocol = protoFactory.getProtocol(transport); ThriftTest.Client testClient = new ThriftTest.Client(protocol); - transport.open(); + open(transport); testVoid(testClient); testString(testClient); testByte(testClient); @@ -403,6 +403,14 @@ public abstract class ServerTestBase extends TestCase { } } + public void open(TTransport transport) throws Exception { + transport.open(); + } + + public List getProtocols() { + return PROTOCOLS; + } + private void testList(ThriftTest.Client testClient) throws TException { List listout = new ArrayList(); for (int i = -2; i < 3; ++i) { diff --git a/lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactory.java b/lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactory.java new file mode 100644 index 00000000..6066f00d --- /dev/null +++ b/lib/java/test/org/apache/thrift/transport/TestTSSLTransportFactory.java @@ -0,0 +1,81 @@ +/* + * 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.thrift.transport; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.thrift.TProcessor; +import org.apache.thrift.protocol.TBinaryProtocol; +import org.apache.thrift.protocol.TProtocolFactory; +import org.apache.thrift.server.ServerTestBase; +import org.apache.thrift.server.TServer; +import org.apache.thrift.server.TSimpleServer; + +public class TestTSSLTransportFactory extends ServerTestBase { + private Thread serverThread; + private TServer server; + + private static final List protocols = new ArrayList(); + static { + // TODO: Only supported on TBinaryProtocol. Doesn't work for TCompactProtocol + protocols.add(new TBinaryProtocol.Factory()); + } + + @Override + public TTransport getClientTransport(TTransport underlyingTransport) + throws Exception { + return TSSLTransportFactory.getClientSocket(HOST, PORT); + } + + @Override + public void startServer(final TProcessor processor, final TProtocolFactory protoFactory) + throws Exception { + serverThread = new Thread() { + public void run() { + try { + TServerTransport serverTransport = TSSLTransportFactory.getServerSocket(PORT); + server = new TSimpleServer(processor, serverTransport); + server.serve(); + } catch (TTransportException e) { + e.printStackTrace(); + assert false; + } + } + }; + + serverThread.start(); + Thread.sleep(1000); + } + + @Override + public void stopServer() throws Exception { + server.stop(); + serverThread.join(); + } + + @Override + public void open(TTransport transport) throws Exception {} + + @Override + public List getProtocols() { + return protocols; + } +} diff --git a/tutorial/java/JavaClient b/tutorial/java/JavaClient index 77b6a057..bc518cf9 100755 --- a/tutorial/java/JavaClient +++ b/tutorial/java/JavaClient @@ -22,4 +22,4 @@ THIS_DIR=$(dirname $0) LIB_DIR=$THIS_DIR/../../lib/java/ IVY_DIR=$LIB_DIR/build/ivy/lib/ -java -cp $IVY_DIR/*:$LIB_DIR/libthrift.jar:tutorial.jar JavaClient +java -cp $IVY_DIR/*:$LIB_DIR/libthrift.jar:tutorial.jar JavaClient $1 diff --git a/tutorial/java/JavaServer b/tutorial/java/JavaServer index 3ff9fd81..d8217153 100755 --- a/tutorial/java/JavaServer +++ b/tutorial/java/JavaServer @@ -22,4 +22,11 @@ THIS_DIR=$(dirname $0) LIB_DIR=$THIS_DIR/../../lib/java/ IVY_DIR=$LIB_DIR/build/ivy/lib/ +# Optionally the following properties could be set for SSL instead +# of configuring it in the code +# -Djavax.net.ssl.trustStore=../../lib/java/test/.truststore +# -Djavax.net.ssl.trustStorePassword=thrift +# -Djavax.net.ssl.keyStore=../../lib/java/test/.keystore +# -Djavax.net.ssl.keyStorePassword=thrift + java -cp $IVY_DIR/*:$LIB_DIR/libthrift.jar:tutorial.jar JavaServer diff --git a/tutorial/java/src/JavaClient.java b/tutorial/java/src/JavaClient.java index 5dc70ed5..ad4730a1 100644 --- a/tutorial/java/src/JavaClient.java +++ b/tutorial/java/src/JavaClient.java @@ -22,64 +22,85 @@ import tutorial.*; import shared.*; import org.apache.thrift.TException; +import org.apache.thrift.transport.TSSLTransportFactory; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TSocket; -import org.apache.thrift.transport.TTransportException; +import org.apache.thrift.transport.TSSLTransportFactory.TSSLTransportParameters; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocol; -import java.util.AbstractMap; -import java.util.HashMap; -import java.util.HashSet; -import java.util.ArrayList; - public class JavaClient { public static void main(String [] args) { - try { - TTransport transport = new TSocket("localhost", 9090); - TProtocol protocol = new TBinaryProtocol(transport); - Calculator.Client client = new Calculator.Client(protocol); + if (args.length != 1) { + System.out.println("Please enter 'simple' or 'secure'"); + System.exit(0); + } - transport.open(); + try { + TTransport transport; + if (args[0].contains("simple")) { + transport = new TSocket("localhost", 9090); + transport.open(); + } + else { + /* + * Similar to the server, you can use the parametrs to setup client parameters or + * use the default settings. On the client side, you will need a TrustStore which + * contains the trusted certificate along with the public key. + * For this example it's a self-signed cert. + */ + TSSLTransportParameters params = new TSSLTransportParameters(); + params.setTrustStore("../../lib/java/test/.truststore", "thrift", "SunX509", "JKS"); + /* + * Get a client transport instead of a server transport. The connection is opened on + * invocation of the factory method, no need to specifically call open() + */ + transport = TSSLTransportFactory.getClientSocket("localhost", 9091, 0, params); + } - client.ping(); - System.out.println("ping()"); + TProtocol protocol = new TBinaryProtocol(transport); + Calculator.Client client = new Calculator.Client(protocol); - int sum = client.add(1,1); - System.out.println("1+1=" + sum); + perform(client); - Work work = new Work(); + transport.close(); + } catch (TException x) { + x.printStackTrace(); + } + } - work.op = Operation.DIVIDE; - work.num1 = 1; - work.num2 = 0; - try { - int quotient = client.calculate(1, work); - System.out.println("Whoa we can divide by 0"); - } catch (InvalidOperation io) { - System.out.println("Invalid operation: " + io.why); - } + private static void perform(Calculator.Client client) throws TException + { + client.ping(); + System.out.println("ping()"); - work.op = Operation.SUBTRACT; - work.num1 = 15; - work.num2 = 10; - try { - int diff = client.calculate(1, work); - System.out.println("15-10=" + diff); - } catch (InvalidOperation io) { - System.out.println("Invalid operation: " + io.why); - } + int sum = client.add(1,1); + System.out.println("1+1=" + sum); - SharedStruct log = client.getStruct(1); - System.out.println("Check log: " + log.value); + Work work = new Work(); - transport.close(); + work.op = Operation.DIVIDE; + work.num1 = 1; + work.num2 = 0; + try { + int quotient = client.calculate(1, work); + System.out.println("Whoa we can divide by 0"); + } catch (InvalidOperation io) { + System.out.println("Invalid operation: " + io.why); + } - } catch (TException x) { - x.printStackTrace(); + work.op = Operation.SUBTRACT; + work.num1 = 15; + work.num2 = 10; + try { + int diff = client.calculate(1, work); + System.out.println("15-10=" + diff); + } catch (InvalidOperation io) { + System.out.println("Invalid operation: " + io.why); } + SharedStruct log = client.getStruct(1); + System.out.println("Check log: " + log.value); } - } diff --git a/tutorial/java/src/JavaServer.java b/tutorial/java/src/JavaServer.java index da84c321..29c4d587 100644 --- a/tutorial/java/src/JavaServer.java +++ b/tutorial/java/src/JavaServer.java @@ -17,13 +17,12 @@ * under the License. */ -import org.apache.thrift.TException; -import org.apache.thrift.protocol.TBinaryProtocol; -import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.server.TServer; import org.apache.thrift.server.TSimpleServer; +import org.apache.thrift.transport.TSSLTransportFactory; import org.apache.thrift.transport.TServerSocket; import org.apache.thrift.transport.TServerTransport; +import org.apache.thrift.transport.TSSLTransportFactory.TSSLTransportParameters; // Generated code import tutorial.*; @@ -54,29 +53,29 @@ public class JavaServer { System.out.println("calculate(" + logid + ", {" + work.op + "," + work.num1 + "," + work.num2 + "})"); int val = 0; switch (work.op) { - case ADD: - val = work.num1 + work.num2; - break; - case SUBTRACT: - val = work.num1 - work.num2; - break; - case MULTIPLY: - val = work.num1 * work.num2; - break; - case DIVIDE: - if (work.num2 == 0) { + case ADD: + val = work.num1 + work.num2; + break; + case SUBTRACT: + val = work.num1 - work.num2; + break; + case MULTIPLY: + val = work.num1 * work.num2; + break; + case DIVIDE: + if (work.num2 == 0) { + InvalidOperation io = new InvalidOperation(); + io.what = work.op.getValue(); + io.why = "Cannot divide by 0"; + throw io; + } + val = work.num1 / work.num2; + break; + default: InvalidOperation io = new InvalidOperation(); io.what = work.op.getValue(); - io.why = "Cannot divide by 0"; + io.why = "Unknown operation"; throw io; - } - val = work.num1 / work.num2; - break; - default: - InvalidOperation io = new InvalidOperation(); - io.what = work.op.getValue(); - io.why = "Unknown operation"; - throw io; } SharedStruct entry = new SharedStruct(); @@ -98,22 +97,75 @@ public class JavaServer { } + public static Calculator.Processor processor; + public static void main(String [] args) { try { CalculatorHandler handler = new CalculatorHandler(); - Calculator.Processor processor = new Calculator.Processor(handler); + processor = new Calculator.Processor(handler); + + Runnable simple = new Runnable() { + public void run() { + simple(processor); + } + }; + Runnable secure = new Runnable() { + public void run() { + secure(processor); + } + }; + + new Thread(simple).start(); + new Thread(secure).start(); + } catch (Exception x) { + x.printStackTrace(); + } + } + + public static void simple(Calculator.Processor processor) { + try { TServerTransport serverTransport = new TServerSocket(9090); TServer server = new TSimpleServer(processor, serverTransport); // Use this for a multithreaded server // server = new TThreadPoolServer(processor, serverTransport); - System.out.println("Starting the server..."); + System.out.println("Starting the simple server..."); server.serve(); + } catch (Exception e) { + e.printStackTrace(); + } + } - } catch (Exception x) { - x.printStackTrace(); + public static void secure(Calculator.Processor processor) { + try { + /* + * Use TSSLTransportParameters to setup the required SSL parameters. In this example + * we are setting the keystore and the keystore password. Other things like algorithms, + * cipher suites, client auth etc can be set. + */ + TSSLTransportParameters params = new TSSLTransportParameters(); + // The Keystore contains the private key + params.setKeyStore("../../lib/java/test/.keystore", "thrift", null, null); + + /* + * Use any of the TSSLTransportFactory to get a server transport with the appropriate + * SSL configuration. You can use the default settings if properties are set in the command line. + * Ex: -Djavax.net.ssl.keyStore=.keystore and -Djavax.net.ssl.keyStorePassword=thrift + * + * Note: You need not explicitly call open(). The underlying server socket is bound on return + * from the factory class. + */ + TServerTransport serverTransport = TSSLTransportFactory.getServerSocket(9091, 0, null, params); + TServer server = new TSimpleServer(processor, serverTransport); + + // Use this for a multi threaded server + // server = new TThreadPoolServer(processor, serverTransport); + + System.out.println("Starting the secure server..."); + server.serve(); + } catch (Exception e) { + e.printStackTrace(); } - System.out.println("done."); } } -- 2.17.1