-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
core: add concrete implementation of managed channel builder
- Loading branch information
Showing
3 changed files
with
333 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
181 changes: 181 additions & 0 deletions
181
core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
/* | ||
* Copyright 2020 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.internal; | ||
|
||
import com.google.common.base.Preconditions; | ||
import io.grpc.ManagedChannelBuilder; | ||
import java.net.SocketAddress; | ||
import java.util.concurrent.Executor; | ||
import javax.annotation.Nullable; | ||
|
||
/** | ||
* Default managed channel builder, for usage in Transport implementations. | ||
*/ | ||
public final class ManagedChannelImplBuilder | ||
extends AbstractManagedChannelImplBuilder<ManagedChannelImplBuilder> { | ||
|
||
private boolean authorityCheckerDisabled; | ||
@Deprecated | ||
@Nullable | ||
private OverrideAuthorityChecker authorityChecker; | ||
|
||
/** | ||
* An interface for Transport implementors to provide the {@link ClientTransportFactory} | ||
* appropriate for the channel. | ||
*/ | ||
public interface ClientTransportFactoryBuilder { | ||
ClientTransportFactory buildClientTransportFactory(); | ||
} | ||
|
||
/** | ||
* An interface for Transport implementors to provide a default port to {@link | ||
* io.grpc.NameResolver} for use in cases where the target string doesn't include a port. The | ||
* default implementation returns {@link GrpcUtil#DEFAULT_PORT_SSL}. | ||
*/ | ||
public interface ChannelBuilderDefaultPortProvider { | ||
int getDefaultPort(); | ||
} | ||
|
||
private class ManagedChannelDefaultPortProvider implements ChannelBuilderDefaultPortProvider { | ||
@Override | ||
public int getDefaultPort() { | ||
return ManagedChannelImplBuilder.super.getDefaultPort(); | ||
} | ||
} | ||
|
||
private final ClientTransportFactoryBuilder clientTransportFactoryBuilder; | ||
private final ChannelBuilderDefaultPortProvider channelBuilderDefaultPortProvider; | ||
|
||
/** | ||
* Creates a new managed channel builder with a target string, which can be either a valid {@link | ||
* io.grpc.NameResolver}-compliant URI, or an authority string. Transport implementors must | ||
* provide client transport factory builder, and may set custom channel default port provider. | ||
*/ | ||
public ManagedChannelImplBuilder(String target, | ||
ClientTransportFactoryBuilder clientTransportFactoryBuilder, | ||
@Nullable ChannelBuilderDefaultPortProvider channelBuilderDefaultPortProvider) { | ||
super(target); | ||
this.clientTransportFactoryBuilder = Preconditions.checkNotNull(clientTransportFactoryBuilder, | ||
"clientTransportFactoryBuilder cannot be null"); | ||
|
||
if (channelBuilderDefaultPortProvider != null) { | ||
this.channelBuilderDefaultPortProvider = channelBuilderDefaultPortProvider; | ||
} else { | ||
this.channelBuilderDefaultPortProvider = new ManagedChannelDefaultPortProvider(); | ||
} | ||
} | ||
|
||
/** | ||
* Creates a new managed channel builder with the given server address, authority string of the | ||
* channel. Transport implementors must provide client transport factory builder, and may set | ||
* custom channel default port provider. | ||
*/ | ||
public ManagedChannelImplBuilder(SocketAddress directServerAddress, String authority, | ||
ClientTransportFactoryBuilder clientTransportFactoryBuilder, | ||
@Nullable ChannelBuilderDefaultPortProvider channelBuilderDefaultPortProvider) { | ||
super(directServerAddress, authority); | ||
this.clientTransportFactoryBuilder = Preconditions.checkNotNull(clientTransportFactoryBuilder, | ||
"clientTransportFactoryBuilder cannot be null"); | ||
|
||
if (channelBuilderDefaultPortProvider != null) { | ||
this.channelBuilderDefaultPortProvider = channelBuilderDefaultPortProvider; | ||
} else { | ||
this.channelBuilderDefaultPortProvider = new ManagedChannelDefaultPortProvider(); | ||
} | ||
} | ||
|
||
@Override | ||
protected ClientTransportFactory buildTransportFactory() { | ||
return clientTransportFactoryBuilder.buildClientTransportFactory(); | ||
} | ||
|
||
@Override | ||
protected int getDefaultPort() { | ||
return channelBuilderDefaultPortProvider.getDefaultPort(); | ||
} | ||
|
||
/** Disable the check whether the authority is valid. */ | ||
public ManagedChannelImplBuilder disableCheckAuthority() { | ||
authorityCheckerDisabled = true; | ||
return this; | ||
} | ||
|
||
/** Enable previously disabled authority check. */ | ||
public ManagedChannelImplBuilder enableCheckAuthority() { | ||
authorityCheckerDisabled = false; | ||
return this; | ||
} | ||
|
||
@Deprecated | ||
public interface OverrideAuthorityChecker { | ||
String checkAuthority(String authority); | ||
} | ||
|
||
@Deprecated | ||
public void overrideAuthorityChecker(@Nullable OverrideAuthorityChecker authorityChecker) { | ||
this.authorityChecker = authorityChecker; | ||
} | ||
|
||
@Override | ||
protected String checkAuthority(String authority) { | ||
if (authorityCheckerDisabled) { | ||
return authority; | ||
} | ||
if (authorityChecker != null) { | ||
return authorityChecker.checkAuthority(authority); | ||
} | ||
return super.checkAuthority(authority); | ||
} | ||
|
||
@Override | ||
public void setStatsEnabled(boolean value) { | ||
super.setStatsEnabled(value); | ||
} | ||
|
||
@Override | ||
public void setStatsRecordStartedRpcs(boolean value) { | ||
super.setStatsRecordStartedRpcs(value); | ||
} | ||
|
||
@Override | ||
public void setStatsRecordFinishedRpcs(boolean value) { | ||
super.setStatsRecordFinishedRpcs(value); | ||
} | ||
|
||
@Override | ||
public void setStatsRecordRealTimeMetrics(boolean value) { | ||
super.setStatsRecordRealTimeMetrics(value); | ||
} | ||
|
||
@Override | ||
public void setTracingEnabled(boolean value) { | ||
super.setTracingEnabled(value); | ||
} | ||
|
||
@Override | ||
public ObjectPool<? extends Executor> getOffloadExecutorPool() { | ||
return super.getOffloadExecutorPool(); | ||
} | ||
|
||
public static ManagedChannelBuilder<?> forAddress(String name, int port) { | ||
throw new UnsupportedOperationException("ClientTransportFactoryBuilder is required"); | ||
} | ||
|
||
public static ManagedChannelBuilder<?> forTarget(String target) { | ||
throw new UnsupportedOperationException("ClientTransportFactoryBuilder is required"); | ||
} | ||
} |
151 changes: 151 additions & 0 deletions
151
core/src/test/java/io/grpc/internal/ManagedChannelImplBuilderTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
/* | ||
* Copyright 2020 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.internal; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
import static org.mockito.Mockito.mock; | ||
import static org.mockito.Mockito.verify; | ||
import static org.mockito.Mockito.when; | ||
|
||
import io.grpc.internal.ManagedChannelImplBuilder.ChannelBuilderDefaultPortProvider; | ||
import io.grpc.internal.ManagedChannelImplBuilder.ClientTransportFactoryBuilder; | ||
import org.junit.Before; | ||
import org.junit.Rule; | ||
import org.junit.Test; | ||
import org.junit.rules.ExpectedException; | ||
import org.junit.runner.RunWith; | ||
import org.junit.runners.JUnit4; | ||
import org.mockito.Mock; | ||
import org.mockito.junit.MockitoJUnit; | ||
import org.mockito.junit.MockitoRule; | ||
|
||
/** Unit tests for {@link ManagedChannelImplBuilder}. */ | ||
@RunWith(JUnit4.class) | ||
public class ManagedChannelImplBuilderTest { | ||
private static final int DUMMY_PORT = 42; | ||
private static final String DUMMY_TARGET = "fake-target"; | ||
private static final String DUMMY_AUTHORITY_VALID = "valid:1234"; | ||
private static final String DUMMY_AUTHORITY_INVALID = "[ : : 1]"; | ||
|
||
@Rule public final MockitoRule mocks = MockitoJUnit.rule(); | ||
@Rule public final ExpectedException thrown = ExpectedException.none(); | ||
|
||
@Mock private ClientTransportFactoryBuilder mockClientTransportFactoryBuilder; | ||
@Mock private ChannelBuilderDefaultPortProvider mockChannelBuilderDefaultPortProvider; | ||
private ManagedChannelImplBuilder builder; | ||
|
||
@Before | ||
public void setUp() throws Exception { | ||
builder = new ManagedChannelImplBuilder( | ||
DUMMY_TARGET, | ||
mockClientTransportFactoryBuilder, | ||
mockChannelBuilderDefaultPortProvider); | ||
} | ||
|
||
/** Ensure buildTransportFactory() delegates to the custom implementation. */ | ||
@Test | ||
public void buildTransportFactory() { | ||
final ClientTransportFactory clientTransportFactory = mock(ClientTransportFactory.class); | ||
when(mockClientTransportFactoryBuilder.buildClientTransportFactory()) | ||
.thenReturn(clientTransportFactory); | ||
assertEquals(clientTransportFactory, builder.buildTransportFactory()); | ||
verify(mockClientTransportFactoryBuilder).buildClientTransportFactory(); | ||
} | ||
|
||
/** Ensure getDefaultPort() returns default port when no custom implementation provided. */ | ||
@Test | ||
public void getDefaultPort_default() { | ||
final ManagedChannelImplBuilder builderNoPortProvider = new ManagedChannelImplBuilder( | ||
DUMMY_TARGET, mockClientTransportFactoryBuilder, null); | ||
assertEquals(GrpcUtil.DEFAULT_PORT_SSL, builderNoPortProvider.getDefaultPort()); | ||
} | ||
|
||
/** Ensure getDefaultPort() delegates to the custom implementation. */ | ||
@Test | ||
public void getDefaultPort_custom() { | ||
when(mockChannelBuilderDefaultPortProvider.getDefaultPort()).thenReturn(DUMMY_PORT); | ||
assertEquals(DUMMY_PORT, builder.getDefaultPort()); | ||
verify(mockChannelBuilderDefaultPortProvider).getDefaultPort(); | ||
} | ||
|
||
@Test | ||
public void checkAuthority_validAuthorityAllowed() { | ||
assertEquals(DUMMY_AUTHORITY_VALID, builder.checkAuthority(DUMMY_AUTHORITY_VALID)); | ||
} | ||
|
||
@Test | ||
public void checkAuthority_invalidAuthorityFailed() { | ||
thrown.expect(IllegalArgumentException.class); | ||
thrown.expectMessage("Invalid authority"); | ||
|
||
builder.checkAuthority(DUMMY_AUTHORITY_INVALID); | ||
} | ||
|
||
@Test | ||
public void disableCheckAuthority_validAuthorityAllowed() { | ||
builder.disableCheckAuthority(); | ||
assertEquals(DUMMY_AUTHORITY_VALID, builder.checkAuthority(DUMMY_AUTHORITY_VALID)); | ||
} | ||
|
||
@Test | ||
public void disableCheckAuthority_invalidAuthorityAllowed() { | ||
builder.disableCheckAuthority(); | ||
assertEquals(DUMMY_AUTHORITY_INVALID, builder.checkAuthority(DUMMY_AUTHORITY_INVALID)); | ||
} | ||
|
||
@Test | ||
public void enableCheckAuthority_validAuthorityAllowed() { | ||
builder.disableCheckAuthority().enableCheckAuthority(); | ||
assertEquals(DUMMY_AUTHORITY_VALID, builder.checkAuthority(DUMMY_AUTHORITY_VALID)); | ||
} | ||
|
||
@Test | ||
public void disableCheckAuthority_invalidAuthorityFailed() { | ||
thrown.expect(IllegalArgumentException.class); | ||
thrown.expectMessage("Invalid authority"); | ||
|
||
builder.disableCheckAuthority().enableCheckAuthority(); | ||
builder.checkAuthority(DUMMY_AUTHORITY_INVALID); | ||
} | ||
|
||
/** Ensure authority check can disabled with custom authority check implementation. */ | ||
@Test | ||
@SuppressWarnings("deprecation") | ||
public void overrideAuthorityChecker_default() { | ||
builder.overrideAuthorityChecker( | ||
new io.grpc.internal.ManagedChannelImplBuilder.OverrideAuthorityChecker() { | ||
@Override public String checkAuthority(String authority) { | ||
return authority; | ||
} | ||
}); | ||
assertEquals(DUMMY_AUTHORITY_INVALID, builder.checkAuthority(DUMMY_AUTHORITY_INVALID)); | ||
} | ||
|
||
/** Ensure custom authority is ignored after disableCheckAuthority(). */ | ||
@Test | ||
@SuppressWarnings("deprecation") | ||
public void overrideAuthorityChecker_ignored() { | ||
builder.overrideAuthorityChecker( | ||
new io.grpc.internal.ManagedChannelImplBuilder.OverrideAuthorityChecker() { | ||
@Override public String checkAuthority(String authority) { | ||
throw new IllegalArgumentException(); | ||
} | ||
}); | ||
builder.disableCheckAuthority(); | ||
assertEquals(DUMMY_AUTHORITY_INVALID, builder.checkAuthority(DUMMY_AUTHORITY_INVALID)); | ||
} | ||
} |