diff options
author | Eric Anderson <ejona@google.com> | 2023-08-09 09:44:18 -0700 |
---|---|---|
committer | Eric Anderson <ejona@google.com> | 2023-08-09 13:58:34 -0700 |
commit | 3b61799f73dc9f52488476c4c92b9e7ce978dc2e (patch) | |
tree | ab3140f0d6a36e8934649214c1fd6a835bcf9d67 | |
parent | a0d8f2eb31c88cf8e9e8d2f213a8cc8ccfb814b0 (diff) | |
download | grpc-grpc-java-3b61799f73dc9f52488476c4c92b9e7ce978dc2e.tar.gz |
okhttp: Add OkHttpServerProvider
This allows okhttp to service the Grpc.newServerBuilderForPort() API.
Note that, unlike Netty, it will throw if you try to use
ServerBuilder.forPort().
This fixes android-interop-testing which was broken by c9864a119.
7 files changed, 171 insertions, 4 deletions
diff --git a/api/src/main/java/io/grpc/ServerRegistry.java b/api/src/main/java/io/grpc/ServerRegistry.java index e6a067ce8..70fd36573 100644 --- a/api/src/main/java/io/grpc/ServerRegistry.java +++ b/api/src/main/java/io/grpc/ServerRegistry.java @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.LinkedHashSet; import java.util.List; +import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; @@ -92,7 +93,7 @@ public final class ServerRegistry { if (instance == null) { List<ServerProvider> providerList = ServiceProviders.loadAll( ServerProvider.class, - Collections.<Class<?>>emptyList(), + getHardCodedClasses(), ServerProvider.class.getClassLoader(), new ServerPriorityAccessor()); instance = new ServerRegistry(); @@ -119,6 +120,20 @@ public final class ServerRegistry { return providers.isEmpty() ? null : providers.get(0); } + @VisibleForTesting + static List<Class<?>> getHardCodedClasses() { + // Class.forName(String) is used to remove the need for ProGuard configuration. Note that + // ProGuard does not detect usages of Class.forName(String, boolean, ClassLoader): + // https://sourceforge.net/p/proguard/bugs/418/ + List<Class<?>> list = new ArrayList<>(); + try { + list.add(Class.forName("io.grpc.okhttp.OkHttpServerProvider")); + } catch (ClassNotFoundException e) { + logger.log(Level.FINE, "Unable to find OkHttpServerProvider", e); + } + return Collections.unmodifiableList(list); + } + ServerBuilder<?> newServerBuilderForPort(int port, ServerCredentials creds) { List<ServerProvider> providers = providers(); if (providers.isEmpty()) { diff --git a/api/src/testFixtures/java/io/grpc/ServerRegistryAccessor.java b/api/src/testFixtures/java/io/grpc/ServerRegistryAccessor.java new file mode 100644 index 000000000..b15d4dfde --- /dev/null +++ b/api/src/testFixtures/java/io/grpc/ServerRegistryAccessor.java @@ -0,0 +1,26 @@ +/* + * Copyright 2023 The gRPC Authors + * + * 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 io.grpc; + +/** Accesses test-only methods of {@link ServerRegistry}. */ +public final class ServerRegistryAccessor { + private ServerRegistryAccessor() {} + + public static Iterable<Class<?>> getHardCodedClasses() { + return ServerRegistry.getHardCodedClasses(); + } +} diff --git a/okhttp/build.gradle b/okhttp/build.gradle index 7d84df436..99f799ec9 100644 --- a/okhttp/build.gradle +++ b/okhttp/build.gradle @@ -50,6 +50,7 @@ tasks.named("checkstyleMain").configure { tasks.named("javadoc").configure { options.links 'http://square.github.io/okhttp/2.x/okhttp/' exclude 'io/grpc/okhttp/Internal*' + exclude 'io/grpc/okhttp/*Provider.java' exclude 'io/grpc/okhttp/internal/**' } diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerBuilder.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerBuilder.java index 45d6b9efc..8269a8ddf 100644 --- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerBuilder.java +++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerBuilder.java @@ -18,7 +18,6 @@ package io.grpc.okhttp; import static com.google.common.base.Preconditions.checkArgument; -import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.DoNotCall; @@ -89,7 +88,7 @@ public final class OkHttpServerBuilder extends ForwardingServerBuilder<OkHttpSer @DoNotCall("Always throws. Use forPort(int, ServerCredentials) instead") @Deprecated public static OkHttpServerBuilder forPort(int port) { - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException("Use forPort(int, ServerCredentials) instead"); } /** @@ -131,7 +130,6 @@ public final class OkHttpServerBuilder extends ForwardingServerBuilder<OkHttpSer long maxConnectionAgeInNanos = MAX_CONNECTION_AGE_NANOS_DISABLED; long maxConnectionAgeGraceInNanos = MAX_CONNECTION_AGE_GRACE_NANOS_INFINITE; - @VisibleForTesting OkHttpServerBuilder( SocketAddress address, HandshakerSocketFactory handshakerSocketFactory) { this.listenAddress = Preconditions.checkNotNull(address, "address"); diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerProvider.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerProvider.java new file mode 100644 index 000000000..ef2fae433 --- /dev/null +++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerProvider.java @@ -0,0 +1,55 @@ +/* + * Copyright 2023 The gRPC Authors + * + * 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 io.grpc.okhttp; + +import io.grpc.Internal; +import io.grpc.ServerCredentials; +import io.grpc.ServerProvider; +import java.net.InetSocketAddress; + +/** Provider for {@link OkHttpServerBuilder} instances. */ +@Internal +public final class OkHttpServerProvider extends ServerProvider { + + @Override + protected boolean isAvailable() { + return true; + } + + @Override + protected int priority() { + // Use a priority less than Netty since builderForPort() always throws. + return 4; + } + + @Override + protected OkHttpServerBuilder builderForPort(int port) { + throw new UnsupportedOperationException("Use Grpc.newServerBuilderForPort() instead"); + } + + @Override + protected NewServerBuilderResult newServerBuilderForPort(int port, ServerCredentials creds) { + OkHttpServerBuilder.HandshakerSocketFactoryResult result = + OkHttpServerBuilder.handshakerSocketFactoryFrom(creds); + if (result.error != null) { + return NewServerBuilderResult.error(result.error); + } + return NewServerBuilderResult.serverBuilder( + new OkHttpServerBuilder(new InetSocketAddress(port), result.factory)); + } +} + diff --git a/okhttp/src/main/resources/META-INF/services/io.grpc.ServerProvider b/okhttp/src/main/resources/META-INF/services/io.grpc.ServerProvider new file mode 100644 index 000000000..263ea4b68 --- /dev/null +++ b/okhttp/src/main/resources/META-INF/services/io.grpc.ServerProvider @@ -0,0 +1 @@ +io.grpc.okhttp.OkHttpServerProvider diff --git a/okhttp/src/test/java/io/grpc/okhttp/OkHttpServerProviderTest.java b/okhttp/src/test/java/io/grpc/okhttp/OkHttpServerProviderTest.java new file mode 100644 index 000000000..93354f01e --- /dev/null +++ b/okhttp/src/test/java/io/grpc/okhttp/OkHttpServerProviderTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2023 The gRPC Authors + * + * 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 io.grpc.okhttp; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; + +import io.grpc.InsecureServerCredentials; +import io.grpc.ServerCredentials; +import io.grpc.ServerProvider; +import io.grpc.ServerRegistryAccessor; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link OkHttpServerProvider}. */ +@RunWith(JUnit4.class) +public class OkHttpServerProviderTest { + private OkHttpServerProvider provider = new OkHttpServerProvider(); + + @Test + public void provided() { + assertThat(ServerProvider.provider()).isInstanceOf(OkHttpServerProvider.class); + } + + @Test + public void providedHardCoded() { + assertThat(ServerRegistryAccessor.getHardCodedClasses()).contains(OkHttpServerProvider.class); + } + + @Test + public void basicMethods() { + assertThat(provider.isAvailable()).isTrue(); + assertThat(provider.priority()).isEqualTo(4); + } + + @Test + public void builderIsAOkHttpBuilder() { + assertThrows(UnsupportedOperationException.class, () -> provider.builderForPort(80)); + } + + @Test + public void newServerBuilderForPort_success() { + ServerProvider.NewServerBuilderResult result = + provider.newServerBuilderForPort(80, InsecureServerCredentials.create()); + assertThat(result.getServerBuilder()).isInstanceOf(OkHttpServerBuilder.class); + } + + @Test + public void newServerBuilderForPort_fail() { + ServerProvider.NewServerBuilderResult result = provider.newServerBuilderForPort( + 80, new FakeServerCredentials()); + assertThat(result.getError()).contains("FakeServerCredentials"); + } + + private static final class FakeServerCredentials extends ServerCredentials {} +} |