diff --git a/alts/src/test/java/io/grpc/alts/internal/AesGcmHkdfAeadCrypterTest.java b/alts/src/test/java/io/grpc/alts/internal/AesGcmHkdfAeadCrypterTest.java
index be69cbd4456..ef64633ea5d 100644
--- a/alts/src/test/java/io/grpc/alts/internal/AesGcmHkdfAeadCrypterTest.java
+++ b/alts/src/test/java/io/grpc/alts/internal/AesGcmHkdfAeadCrypterTest.java
@@ -18,10 +18,10 @@
import static com.google.common.truth.Truth.assertWithMessage;
+import com.google.common.io.BaseEncoding;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.util.Arrays;
-import javax.xml.bind.DatatypeConverter;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -78,27 +78,27 @@ TestVectorBuilder withComment(String comment) {
}
TestVectorBuilder withKey(String key) {
- this.key = DatatypeConverter.parseHexBinary(key);
+ this.key = BaseEncoding.base16().lowerCase().decode(key);
return this;
}
TestVectorBuilder withNonce(String nonce) {
- this.nonce = DatatypeConverter.parseHexBinary(nonce);
+ this.nonce = BaseEncoding.base16().lowerCase().decode(nonce);
return this;
}
TestVectorBuilder withAad(String aad) {
- this.aad = DatatypeConverter.parseHexBinary(aad);
+ this.aad = BaseEncoding.base16().lowerCase().decode(aad);
return this;
}
TestVectorBuilder withPlaintext(String plaintext) {
- this.plaintext = DatatypeConverter.parseHexBinary(plaintext);
+ this.plaintext = BaseEncoding.base16().lowerCase().decode(plaintext);
return this;
}
TestVectorBuilder withCiphertext(String ciphertext) {
- this.ciphertext = DatatypeConverter.parseHexBinary(ciphertext);
+ this.ciphertext = BaseEncoding.base16().lowerCase().decode(ciphertext);
return this;
}
}
diff --git a/interop-testing/src/test/java/io/grpc/ChannelAndServerBuilderTest.java b/interop-testing/src/test/java/io/grpc/ChannelAndServerBuilderTest.java
index ac830b98485..15c91d1d136 100644
--- a/interop-testing/src/test/java/io/grpc/ChannelAndServerBuilderTest.java
+++ b/interop-testing/src/test/java/io/grpc/ChannelAndServerBuilderTest.java
@@ -36,6 +36,8 @@
/**
* Tests that Channel and Server builders properly hide the static constructors.
+ *
+ *
This test does nothing on Java 9.
*/
@RunWith(Parameterized.class)
public class ChannelAndServerBuilderTest {
@@ -49,13 +51,19 @@ public class ChannelAndServerBuilderTest {
@Parameters(name = "class={0}")
public static Collection params() throws Exception {
ClassLoader loader = ChannelAndServerBuilderTest.class.getClassLoader();
+ Collection classInfos =
+ ClassPath.from(loader).getTopLevelClassesRecursive("io.grpc");
+ // Java 9 doesn't expose the URLClassLoader, which breaks searching through the classpath
+ if (classInfos.isEmpty()) {
+ return new ArrayList();
+ }
List classes = new ArrayList();
- for (ClassInfo classInfo : ClassPath.from(loader).getTopLevelClassesRecursive("io.grpc")) {
+ for (ClassInfo classInfo : classInfos) {
Class> clazz = Class.forName(classInfo.getName(), false /*initialize*/, loader);
if (ServerBuilder.class.isAssignableFrom(clazz) && clazz != ServerBuilder.class) {
classes.add(new Object[]{clazz});
} else if (ManagedChannelBuilder.class.isAssignableFrom(clazz)
- && clazz != ManagedChannelBuilder.class ) {
+ && clazz != ManagedChannelBuilder.class) {
classes.add(new Object[]{clazz});
}
}
diff --git a/okhttp/src/test/java/io/grpc/okhttp/OkHttpProtocolNegotiatorTest.java b/okhttp/src/test/java/io/grpc/okhttp/OkHttpProtocolNegotiatorTest.java
index 2ac31ea51f5..4e836eec541 100644
--- a/okhttp/src/test/java/io/grpc/okhttp/OkHttpProtocolNegotiatorTest.java
+++ b/okhttp/src/test/java/io/grpc/okhttp/OkHttpProtocolNegotiatorTest.java
@@ -19,6 +19,7 @@
import static com.google.common.base.Charsets.UTF_8;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -32,6 +33,7 @@
import io.grpc.okhttp.internal.Protocol;
import java.io.IOException;
import javax.net.ssl.HandshakeCompletedListener;
+import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import org.junit.Rule;
@@ -110,7 +112,9 @@ public void negotiatorNotNull() {
@Test
public void negotiate_handshakeFails() throws IOException {
+ SSLParameters parameters = new SSLParameters();
OkHttpProtocolNegotiator negotiator = OkHttpProtocolNegotiator.get();
+ doReturn(parameters).when(sock).getSSLParameters();
doThrow(new IOException()).when(sock).startHandshake();
thrown.expect(IOException.class);
diff --git a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/Platform.java b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/Platform.java
index fb040d01a4e..d6f88ba0e95 100644
--- a/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/Platform.java
+++ b/okhttp/third_party/okhttp/java/io/grpc/okhttp/internal/Platform.java
@@ -29,7 +29,11 @@
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
+import java.security.AccessController;
+import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
import java.security.Provider;
import java.security.Security;
import java.util.ArrayList;
@@ -37,6 +41,8 @@
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import okio.Buffer;
@@ -44,19 +50,25 @@
* Access to platform-specific features.
*
* Server name indication (SNI)
+ *
* Supported on Android 2.3+.
*
* Session Tickets
+ *
* Supported on Android 2.3+.
*
* Android Traffic Stats (Socket Tagging)
+ *
* Supported on Android 4.0+.
*
* ALPN (Application Layer Protocol Negotiation)
+ *
* Supported on Android 5.0+. The APIs were present in Android 4.4, but that implementation was
* unstable.
*
- * Supported on OpenJDK 7 and 8 (via the JettyALPN-boot library).
+ * Supported on OpenJDK 9+.
+ *
+ *
Supported on OpenJDK 7 and 8 (via the JettyALPN-boot library).
*/
public class Platform {
public static final Logger logger = Logger.getLogger(Platform.class.getName());
@@ -199,6 +211,47 @@ private static Platform findPlatform() {
throw new RuntimeException(nsae);
}
+ // Find JDK9+ ALPN support
+ try {
+ // getApplicationProtocol() may throw UnsupportedOperationException, so first construct a
+ // dummy SSLEngine and verify the method does not throw.
+ SSLContext context = SSLContext.getInstance("TLS", sslProvider);
+ context.init(null, null, null);
+ SSLEngine engine = context.createSSLEngine();
+ Method getEngineApplicationProtocol =
+ AccessController.doPrivileged(
+ new PrivilegedExceptionAction() {
+ @Override
+ public Method run() throws Exception {
+ return SSLEngine.class.getMethod("getApplicationProtocol");
+ }
+ });
+ getEngineApplicationProtocol.invoke(engine);
+
+ Method setApplicationProtocols =
+ AccessController.doPrivileged(
+ new PrivilegedExceptionAction() {
+ @Override
+ public Method run() throws Exception {
+ return SSLParameters.class.getMethod("setApplicationProtocols", String[].class);
+ }
+ });
+ Method getApplicationProtocol =
+ AccessController.doPrivileged(
+ new PrivilegedExceptionAction() {
+ @Override
+ public Method run() throws Exception {
+ return SSLSocket.class.getMethod("getApplicationProtocol");
+ }
+ });
+ return new JdkAlpnPlatform(sslProvider, setApplicationProtocols, getApplicationProtocol);
+ } catch (NoSuchAlgorithmException ignored) {
+ } catch (KeyManagementException ignored) {
+ } catch (PrivilegedActionException ignored) {
+ } catch (IllegalAccessException ignored) {
+ } catch (InvocationTargetException ignored) {
+ }
+
// Find Jetty's ALPN extension for OpenJDK.
try {
String negoClassName = "org.eclipse.jetty.alpn.ALPN";
@@ -375,6 +428,56 @@ public TlsExtensionType getTlsExtensionType() {
}
}
+ /** OpenJDK 9+. */
+ private static class JdkAlpnPlatform extends Platform {
+ private final Method setApplicationProtocols;
+ private final Method getApplicationProtocol;
+
+ private JdkAlpnPlatform(
+ Provider provider, Method setApplicationProtocols, Method getApplicationProtocol) {
+ super(provider);
+ this.setApplicationProtocols = setApplicationProtocols;
+ this.getApplicationProtocol = getApplicationProtocol;
+ }
+
+ @Override
+ public TlsExtensionType getTlsExtensionType() {
+ return TlsExtensionType.ALPN_AND_NPN;
+ }
+
+ @Override
+ public void configureTlsExtensions(
+ SSLSocket sslSocket, String hostname, List protocols) {
+ SSLParameters parameters = sslSocket.getSSLParameters();
+ List names = new ArrayList(protocols.size());
+ for (Protocol protocol : protocols) {
+ if (protocol == Protocol.HTTP_1_0) continue; // No HTTP/1.0 for ALPN.
+ names.add(protocol.toString());
+ }
+ try {
+ setApplicationProtocols.invoke(
+ parameters, new Object[] {names.toArray(new String[names.size()])});
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ sslSocket.setSSLParameters(parameters);
+ }
+
+ /** Returns the negotiated protocol, or null if no protocol was negotiated. */
+ @Override
+ public String getSelectedProtocol(SSLSocket socket) {
+ try {
+ return (String) getApplicationProtocol.invoke(socket);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
/**
* OpenJDK 7+ with {@code org.mortbay.jetty.alpn/alpn-boot} in the boot class path.
*/