Skip to content

Commit e7afdb3

Browse files
committed
core: add concrete implementation of managed channel builder
1 parent 292f3b9 commit e7afdb3

3 files changed

Lines changed: 333 additions & 1 deletion

File tree

core/src/main/java/io/grpc/internal/AbstractManagedChannelImplBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
import javax.annotation.Nullable;
5252

5353
/**
54-
* The base class for channel builders.
54+
* Abstract base class for channel builders.
5555
*
5656
* @param <T> The concrete type of this builder.
5757
*/
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
/*
2+
* Copyright 2020 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.internal;
18+
19+
import com.google.common.base.Preconditions;
20+
import io.grpc.ManagedChannelBuilder;
21+
import java.net.SocketAddress;
22+
import java.util.concurrent.Executor;
23+
import javax.annotation.Nullable;
24+
25+
/**
26+
* Default managed channel builder, for usage in Transport implementations.
27+
*/
28+
public final class ManagedChannelImplBuilder
29+
extends AbstractManagedChannelImplBuilder<ManagedChannelImplBuilder> {
30+
31+
private boolean authorityCheckerDisabled;
32+
@Deprecated
33+
@Nullable
34+
private OverrideAuthorityChecker authorityChecker;
35+
36+
/**
37+
* An interface for Transport implementors to provide the {@link ClientTransportFactory}
38+
* appropriate for the channel.
39+
*/
40+
public interface ClientTransportFactoryBuilder {
41+
ClientTransportFactory buildClientTransportFactory();
42+
}
43+
44+
/**
45+
* An interface for Transport implementors to provide a default port to {@link
46+
* io.grpc.NameResolver} for use in cases where the target string doesn't include a port. The
47+
* default implementation returns {@link GrpcUtil#DEFAULT_PORT_SSL}.
48+
*/
49+
public interface ChannelBuilderDefaultPortProvider {
50+
int getDefaultPort();
51+
}
52+
53+
private class ManagedChannelDefaultPortProvider implements ChannelBuilderDefaultPortProvider {
54+
@Override
55+
public int getDefaultPort() {
56+
return ManagedChannelImplBuilder.super.getDefaultPort();
57+
}
58+
}
59+
60+
private final ClientTransportFactoryBuilder clientTransportFactoryBuilder;
61+
private final ChannelBuilderDefaultPortProvider channelBuilderDefaultPortProvider;
62+
63+
/**
64+
* Creates a new managed channel builder with a target string, which can be either a valid {@link
65+
* io.grpc.NameResolver}-compliant URI, or an authority string. Transport implementors must
66+
* provide client transport factory builder, and may set custom channel default port provider.
67+
*/
68+
public ManagedChannelImplBuilder(String target,
69+
ClientTransportFactoryBuilder clientTransportFactoryBuilder,
70+
@Nullable ChannelBuilderDefaultPortProvider channelBuilderDefaultPortProvider) {
71+
super(target);
72+
this.clientTransportFactoryBuilder = Preconditions.checkNotNull(clientTransportFactoryBuilder,
73+
"clientTransportFactoryBuilder cannot be null");
74+
75+
if (channelBuilderDefaultPortProvider != null) {
76+
this.channelBuilderDefaultPortProvider = channelBuilderDefaultPortProvider;
77+
} else {
78+
this.channelBuilderDefaultPortProvider = new ManagedChannelDefaultPortProvider();
79+
}
80+
}
81+
82+
/**
83+
* Creates a new managed channel builder with the given server address, authority string of the
84+
* channel. Transport implementors must provide client transport factory builder, and may set
85+
* custom channel default port provider.
86+
*/
87+
public ManagedChannelImplBuilder(SocketAddress directServerAddress, String authority,
88+
ClientTransportFactoryBuilder clientTransportFactoryBuilder,
89+
@Nullable ChannelBuilderDefaultPortProvider channelBuilderDefaultPortProvider) {
90+
super(directServerAddress, authority);
91+
this.clientTransportFactoryBuilder = Preconditions.checkNotNull(clientTransportFactoryBuilder,
92+
"clientTransportFactoryBuilder cannot be null");
93+
94+
if (channelBuilderDefaultPortProvider != null) {
95+
this.channelBuilderDefaultPortProvider = channelBuilderDefaultPortProvider;
96+
} else {
97+
this.channelBuilderDefaultPortProvider = new ManagedChannelDefaultPortProvider();
98+
}
99+
}
100+
101+
@Override
102+
protected ClientTransportFactory buildTransportFactory() {
103+
return clientTransportFactoryBuilder.buildClientTransportFactory();
104+
}
105+
106+
@Override
107+
protected int getDefaultPort() {
108+
return channelBuilderDefaultPortProvider.getDefaultPort();
109+
}
110+
111+
/** Disable the check whether the authority is valid. */
112+
public ManagedChannelImplBuilder disableCheckAuthority() {
113+
authorityCheckerDisabled = true;
114+
return this;
115+
}
116+
117+
/** Enable previously disabled authority check. */
118+
public ManagedChannelImplBuilder enableCheckAuthority() {
119+
authorityCheckerDisabled = false;
120+
return this;
121+
}
122+
123+
@Deprecated
124+
public interface OverrideAuthorityChecker {
125+
String checkAuthority(String authority);
126+
}
127+
128+
@Deprecated
129+
public void overrideAuthorityChecker(@Nullable OverrideAuthorityChecker authorityChecker) {
130+
this.authorityChecker = authorityChecker;
131+
}
132+
133+
@Override
134+
protected String checkAuthority(String authority) {
135+
if (authorityCheckerDisabled) {
136+
return authority;
137+
}
138+
if (authorityChecker != null) {
139+
return authorityChecker.checkAuthority(authority);
140+
}
141+
return super.checkAuthority(authority);
142+
}
143+
144+
@Override
145+
public void setStatsEnabled(boolean value) {
146+
super.setStatsEnabled(value);
147+
}
148+
149+
@Override
150+
public void setStatsRecordStartedRpcs(boolean value) {
151+
super.setStatsRecordStartedRpcs(value);
152+
}
153+
154+
@Override
155+
public void setStatsRecordFinishedRpcs(boolean value) {
156+
super.setStatsRecordFinishedRpcs(value);
157+
}
158+
159+
@Override
160+
public void setStatsRecordRealTimeMetrics(boolean value) {
161+
super.setStatsRecordRealTimeMetrics(value);
162+
}
163+
164+
@Override
165+
public void setTracingEnabled(boolean value) {
166+
super.setTracingEnabled(value);
167+
}
168+
169+
@Override
170+
public ObjectPool<? extends Executor> getOffloadExecutorPool() {
171+
return super.getOffloadExecutorPool();
172+
}
173+
174+
public static ManagedChannelBuilder<?> forAddress(String name, int port) {
175+
throw new UnsupportedOperationException("ClientTransportFactoryBuilder is required");
176+
}
177+
178+
public static ManagedChannelBuilder<?> forTarget(String target) {
179+
throw new UnsupportedOperationException("ClientTransportFactoryBuilder is required");
180+
}
181+
}
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
* Copyright 2020 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.internal;
18+
19+
import static org.junit.Assert.assertEquals;
20+
import static org.mockito.Mockito.mock;
21+
import static org.mockito.Mockito.verify;
22+
import static org.mockito.Mockito.when;
23+
24+
import io.grpc.internal.ManagedChannelImplBuilder.ChannelBuilderDefaultPortProvider;
25+
import io.grpc.internal.ManagedChannelImplBuilder.ClientTransportFactoryBuilder;
26+
import org.junit.Before;
27+
import org.junit.Rule;
28+
import org.junit.Test;
29+
import org.junit.rules.ExpectedException;
30+
import org.junit.runner.RunWith;
31+
import org.junit.runners.JUnit4;
32+
import org.mockito.Mock;
33+
import org.mockito.junit.MockitoJUnit;
34+
import org.mockito.junit.MockitoRule;
35+
36+
/** Unit tests for {@link ManagedChannelImplBuilder}. */
37+
@RunWith(JUnit4.class)
38+
public class ManagedChannelImplBuilderTest {
39+
private static final int DUMMY_PORT = 42;
40+
private static final String DUMMY_TARGET = "fake-target";
41+
private static final String DUMMY_AUTHORITY_VALID = "valid:1234";
42+
private static final String DUMMY_AUTHORITY_INVALID = "[ : : 1]";
43+
44+
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
45+
@Rule public final ExpectedException thrown = ExpectedException.none();
46+
47+
@Mock private ClientTransportFactoryBuilder mockClientTransportFactoryBuilder;
48+
@Mock private ChannelBuilderDefaultPortProvider mockChannelBuilderDefaultPortProvider;
49+
private ManagedChannelImplBuilder builder;
50+
51+
@Before
52+
public void setUp() throws Exception {
53+
builder = new ManagedChannelImplBuilder(
54+
DUMMY_TARGET,
55+
mockClientTransportFactoryBuilder,
56+
mockChannelBuilderDefaultPortProvider);
57+
}
58+
59+
/** Ensure buildTransportFactory() delegates to the custom implementation. */
60+
@Test
61+
public void buildTransportFactory() {
62+
final ClientTransportFactory clientTransportFactory = mock(ClientTransportFactory.class);
63+
when(mockClientTransportFactoryBuilder.buildClientTransportFactory())
64+
.thenReturn(clientTransportFactory);
65+
assertEquals(clientTransportFactory, builder.buildTransportFactory());
66+
verify(mockClientTransportFactoryBuilder).buildClientTransportFactory();
67+
}
68+
69+
/** Ensure getDefaultPort() returns default port when no custom implementation provided. */
70+
@Test
71+
public void getDefaultPort_default() {
72+
final ManagedChannelImplBuilder builderNoPortProvider = new ManagedChannelImplBuilder(
73+
DUMMY_TARGET, mockClientTransportFactoryBuilder, null);
74+
assertEquals(GrpcUtil.DEFAULT_PORT_SSL, builderNoPortProvider.getDefaultPort());
75+
}
76+
77+
/** Ensure getDefaultPort() delegates to the custom implementation. */
78+
@Test
79+
public void getDefaultPort_custom() {
80+
when(mockChannelBuilderDefaultPortProvider.getDefaultPort()).thenReturn(DUMMY_PORT);
81+
assertEquals(DUMMY_PORT, builder.getDefaultPort());
82+
verify(mockChannelBuilderDefaultPortProvider).getDefaultPort();
83+
}
84+
85+
@Test
86+
public void checkAuthority_validAuthorityAllowed() {
87+
assertEquals(DUMMY_AUTHORITY_VALID, builder.checkAuthority(DUMMY_AUTHORITY_VALID));
88+
}
89+
90+
@Test
91+
public void checkAuthority_invalidAuthorityFailed() {
92+
thrown.expect(IllegalArgumentException.class);
93+
thrown.expectMessage("Invalid authority");
94+
95+
builder.checkAuthority(DUMMY_AUTHORITY_INVALID);
96+
}
97+
98+
@Test
99+
public void disableCheckAuthority_validAuthorityAllowed() {
100+
builder.disableCheckAuthority();
101+
assertEquals(DUMMY_AUTHORITY_VALID, builder.checkAuthority(DUMMY_AUTHORITY_VALID));
102+
}
103+
104+
@Test
105+
public void disableCheckAuthority_invalidAuthorityAllowed() {
106+
builder.disableCheckAuthority();
107+
assertEquals(DUMMY_AUTHORITY_INVALID, builder.checkAuthority(DUMMY_AUTHORITY_INVALID));
108+
}
109+
110+
@Test
111+
public void enableCheckAuthority_validAuthorityAllowed() {
112+
builder.disableCheckAuthority().enableCheckAuthority();
113+
assertEquals(DUMMY_AUTHORITY_VALID, builder.checkAuthority(DUMMY_AUTHORITY_VALID));
114+
}
115+
116+
@Test
117+
public void disableCheckAuthority_invalidAuthorityFailed() {
118+
thrown.expect(IllegalArgumentException.class);
119+
thrown.expectMessage("Invalid authority");
120+
121+
builder.disableCheckAuthority().enableCheckAuthority();
122+
builder.checkAuthority(DUMMY_AUTHORITY_INVALID);
123+
}
124+
125+
/** Ensure authority check can disabled with custom authority check implementation. */
126+
@Test
127+
@SuppressWarnings("deprecation")
128+
public void overrideAuthorityChecker_default() {
129+
builder.overrideAuthorityChecker(
130+
new io.grpc.internal.ManagedChannelImplBuilder.OverrideAuthorityChecker() {
131+
@Override public String checkAuthority(String authority) {
132+
return authority;
133+
}
134+
});
135+
assertEquals(DUMMY_AUTHORITY_INVALID, builder.checkAuthority(DUMMY_AUTHORITY_INVALID));
136+
}
137+
138+
/** Ensure custom authority is ignored after disableCheckAuthority(). */
139+
@Test
140+
@SuppressWarnings("deprecation")
141+
public void overrideAuthorityChecker_ignored() {
142+
builder.overrideAuthorityChecker(
143+
new io.grpc.internal.ManagedChannelImplBuilder.OverrideAuthorityChecker() {
144+
@Override public String checkAuthority(String authority) {
145+
throw new IllegalArgumentException();
146+
}
147+
});
148+
builder.disableCheckAuthority();
149+
assertEquals(DUMMY_AUTHORITY_INVALID, builder.checkAuthority(DUMMY_AUTHORITY_INVALID));
150+
}
151+
}

0 commit comments

Comments
 (0)