Skip to content

Commit c368a0f

Browse files
authored
Migrate GlobalInterceptors to ConfiguratorRegistry
This should preserve all the existing behavior of GlobalInterceptors as used by grpc-gcp-observability, including it disabling the implicit OpenCensus integration. Both the old and new API are internal. I hid Configurator and ConfiguratorRegistry behind Internal-prefixed classes, like had been done with GlobalInterceptors to further discourage use until the API is ready. GlobalInterceptorsTest was modified to become ConfiguratorRegistryTest.
1 parent 077dcbf commit c368a0f

File tree

16 files changed

+309
-413
lines changed

16 files changed

+309
-413
lines changed

api/src/main/java/io/grpc/Configurator.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@
1919
/**
2020
* Provides hooks for modifying gRPC channels and servers during their construction.
2121
*/
22-
@Internal
23-
public interface Configurator {
22+
interface Configurator {
2423
/**
2524
* Allows implementations to modify the channel builder.
2625
*

api/src/main/java/io/grpc/ConfiguratorRegistry.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,22 @@
1919
import java.util.ArrayList;
2020
import java.util.Collections;
2121
import java.util.List;
22+
import javax.annotation.concurrent.GuardedBy;
2223

2324
/**
2425
* A registry for {@link Configurator} instances.
2526
*
2627
* <p>This class is responsible for maintaining a list of configurators and providing access to
2728
* them. The default registry can be obtained using {@link #getDefaultRegistry()}.
2829
*/
29-
@Internal
30-
public final class ConfiguratorRegistry {
30+
final class ConfiguratorRegistry {
3131
private static ConfiguratorRegistry instance;
32-
private static boolean isConfiguratorsSet;
32+
33+
@GuardedBy("this")
34+
private boolean wasConfiguratorsSet;
35+
@GuardedBy("this")
36+
private boolean configFrozen;
37+
@GuardedBy("this")
3338
private List<Configurator> configurators = Collections.emptyList();
3439

3540
ConfiguratorRegistry() {}
@@ -50,18 +55,24 @@ public static synchronized ConfiguratorRegistry getDefaultRegistry() {
5055
* @param configurators the configurators to set
5156
* @throws IllegalStateException if this method is called more than once
5257
*/
53-
public synchronized void setConfigurators(List<Configurator> configurators) {
54-
if (isConfiguratorsSet) {
58+
public synchronized void setConfigurators(List<? extends Configurator> configurators) {
59+
if (configFrozen) {
5560
throw new IllegalStateException("Configurators are already set");
5661
}
57-
configurators = Collections.unmodifiableList(new ArrayList<>(configurators));
58-
isConfiguratorsSet = true;
62+
this.configurators = Collections.unmodifiableList(new ArrayList<>(configurators));
63+
configFrozen = true;
64+
wasConfiguratorsSet = true;
5965
}
6066

6167
/**
6268
* Returns a list of the configurators in this registry.
6369
*/
6470
public synchronized List<Configurator> getConfigurators() {
71+
configFrozen = true;
6572
return configurators;
6673
}
74+
75+
public synchronized boolean wasSetConfiguratorsCalled() {
76+
return wasConfiguratorsSet;
77+
}
6778
}

api/src/main/java/io/grpc/GlobalInterceptors.java

Lines changed: 0 additions & 93 deletions
This file was deleted.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright 2024 The gRPC Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.grpc;
18+
19+
/**
20+
* Internal access to Configurator API.
21+
*/
22+
@Internal
23+
public interface InternalConfigurator extends Configurator {}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright 2024 The gRPC Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.grpc;
18+
19+
import java.util.List;
20+
21+
/**
22+
* Access internal global configurators.
23+
*/
24+
@Internal
25+
public final class InternalConfiguratorRegistry {
26+
private InternalConfiguratorRegistry() {}
27+
28+
public static void setConfigurators(List<InternalConfigurator> configurators) {
29+
ConfiguratorRegistry.getDefaultRegistry().setConfigurators(configurators);
30+
}
31+
32+
public static List<?> getConfigurators() {
33+
return ConfiguratorRegistry.getDefaultRegistry().getConfigurators();
34+
}
35+
36+
public static void configureChannelBuilder(ManagedChannelBuilder<?> channelBuilder) {
37+
for (Configurator configurator : ConfiguratorRegistry.getDefaultRegistry().getConfigurators()) {
38+
configurator.configureChannelBuilder(channelBuilder);
39+
}
40+
}
41+
42+
public static void configureServerBuilder(ServerBuilder<?> serverBuilder) {
43+
for (Configurator configurator : ConfiguratorRegistry.getDefaultRegistry().getConfigurators()) {
44+
configurator.configureServerBuilder(serverBuilder);
45+
}
46+
}
47+
48+
public static boolean wasSetConfiguratorsCalled() {
49+
return ConfiguratorRegistry.getDefaultRegistry().wasSetConfiguratorsCalled();
50+
}
51+
}

api/src/main/java/io/grpc/InternalGlobalInterceptors.java

Lines changed: 0 additions & 46 deletions
This file was deleted.
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright 2022 The gRPC Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.grpc;
18+
19+
import static com.google.common.truth.Truth.assertThat;
20+
import static org.junit.Assert.fail;
21+
22+
import java.util.Arrays;
23+
import java.util.List;
24+
import java.util.regex.Pattern;
25+
import org.junit.Test;
26+
import org.junit.runner.RunWith;
27+
import org.junit.runners.JUnit4;
28+
29+
@RunWith(JUnit4.class)
30+
public class ConfiguratorRegistryTest {
31+
32+
private final StaticTestingClassLoader classLoader =
33+
new StaticTestingClassLoader(
34+
getClass().getClassLoader(), Pattern.compile("io\\.grpc\\.[^.]+"));
35+
36+
@Test
37+
public void setConfigurators() throws Exception {
38+
Class<?> runnable = classLoader.loadClass(StaticTestingClassLoaderSet.class.getName());
39+
((Runnable) runnable.getDeclaredConstructor().newInstance()).run();
40+
}
41+
42+
@Test
43+
public void setGlobalConfigurators_twice() throws Exception {
44+
Class<?> runnable = classLoader.loadClass(StaticTestingClassLoaderSetTwice.class.getName());
45+
((Runnable) runnable.getDeclaredConstructor().newInstance()).run();
46+
}
47+
48+
@Test
49+
public void getBeforeSet() throws Exception {
50+
Class<?> runnable =
51+
classLoader.loadClass(
52+
StaticTestingClassLoaderGetBeforeSet.class.getName());
53+
((Runnable) runnable.getDeclaredConstructor().newInstance()).run();
54+
}
55+
56+
// UsedReflectively
57+
public static final class StaticTestingClassLoaderSet implements Runnable {
58+
@Override
59+
public void run() {
60+
List<Configurator> configurators = Arrays.asList(new NoopConfigurator());
61+
62+
ConfiguratorRegistry.getDefaultRegistry().setConfigurators(configurators);
63+
64+
assertThat(ConfiguratorRegistry.getDefaultRegistry().getConfigurators())
65+
.isEqualTo(configurators);
66+
}
67+
}
68+
69+
public static final class StaticTestingClassLoaderSetTwice implements Runnable {
70+
@Override
71+
public void run() {
72+
ConfiguratorRegistry.getDefaultRegistry()
73+
.setConfigurators(Arrays.asList(new NoopConfigurator()));
74+
try {
75+
ConfiguratorRegistry.getDefaultRegistry()
76+
.setConfigurators(Arrays.asList(new NoopConfigurator()));
77+
fail("should have failed for calling setConfigurators() again");
78+
} catch (IllegalStateException e) {
79+
assertThat(e).hasMessageThat().isEqualTo("Configurators are already set");
80+
}
81+
}
82+
}
83+
84+
public static final class StaticTestingClassLoaderGetBeforeSet implements Runnable {
85+
@Override
86+
public void run() {
87+
assertThat(ConfiguratorRegistry.getDefaultRegistry().getConfigurators()).isEmpty();
88+
89+
try {
90+
ConfiguratorRegistry.getDefaultRegistry()
91+
.setConfigurators(Arrays.asList(new NoopConfigurator()));
92+
fail("should have failed for invoking set call after get is already called");
93+
} catch (IllegalStateException e) {
94+
assertThat(e).hasMessageThat().isEqualTo("Configurators are already set");
95+
}
96+
}
97+
}
98+
99+
private static class NoopConfigurator implements Configurator {}
100+
}

0 commit comments

Comments
 (0)